/* This is a heavily customized and minimized copy of Lua 5.1.5. */
/* It's only used to build LuaJIT. It does NOT have all standard functions! */
/******************************************************************************
* Copyright (C) 1994-2012 Lua.org, PUC-Rio.  All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
#ifdef _MSC_VER
typedef unsigned __int64 U64;
#else
typedef unsigned long long U64;
#endif
int _CRT_glob = 0;
#include <stddef.h>
#include <stdarg.h>
#include <limits.h>
#include <math.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <errno.h>
#include <time.h>
typedef enum {
	TM_INDEX,
	TM_NEWINDEX,
	TM_GC,
	TM_MODE,
	TM_EQ,
	TM_ADD,
	TM_SUB,
	TM_MUL,
	TM_DIV,
	TM_MOD,
	TM_POW,
	TM_UNM,
	TM_LEN,
	TM_LT,
	TM_LE,
	TM_CONCAT,
	TM_CALL,
	TM_N
} TMS;
enum OpMode { iABC, iABx, iAsBx };
typedef enum {
	OP_MOVE,
	OP_LOADK,
	OP_LOADBOOL,
	OP_LOADNIL,
	OP_GETUPVAL,
	OP_GETGLOBAL,
	OP_GETTABLE,
	OP_SETGLOBAL,
	OP_SETUPVAL,
	OP_SETTABLE,
	OP_NEWTABLE,
	OP_SELF,
	OP_ADD,
	OP_SUB,
	OP_MUL,
	OP_DIV,
	OP_MOD,
	OP_POW,
	OP_UNM,
	OP_NOT,
	OP_LEN,
	OP_CONCAT,
	OP_JMP,
	OP_EQ,
	OP_LT,
	OP_LE,
	OP_TEST,
	OP_TESTSET,
	OP_CALL,
	OP_TAILCALL,
	OP_RETURN,
	OP_FORLOOP,
	OP_FORPREP,
	OP_TFORLOOP,
	OP_SETLIST,
	OP_CLOSE,
	OP_CLOSURE,
	OP_VARARG
} OpCode;
enum OpArgMask {
	OpArgN,
	OpArgU,
	OpArgR,
	OpArgK
};
typedef enum {
	VVOID,
	VNIL,
	VTRUE,
	VFALSE,
	VK,
	VKNUM,
	VLOCAL,
	VUPVAL,
	VGLOBAL,
	VINDEXED,
	VJMP,
	VRELOCABLE,
	VNONRELOC,
	VCALL,
	VVARARG
} expkind;
enum RESERVED {
	TK_AND = 257, TK_BREAK,
	TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
	TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
	TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
	TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
	TK_NAME, TK_STRING, TK_EOS
};
typedef enum BinOpr {
	OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,
	OPR_CONCAT,
	OPR_NE, OPR_EQ,
	OPR_LT, OPR_LE, OPR_GT, OPR_GE,
	OPR_AND, OPR_OR,
	OPR_NOBINOPR
} BinOpr;
typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
#define LUA_QL(x)"'"x"'"
#define luai_apicheck(L,o){(void)L;}
#define lua_number2str(s,n)sprintf((s),"%.14g",(n))
#define lua_str2number(s,p)strtod((s),(p))
#define luai_numadd(a,b)((a)+(b))
#define luai_numsub(a,b)((a)-(b))
#define luai_nummul(a,b)((a)*(b))
#define luai_numdiv(a,b)((a)/(b))
#define luai_nummod(a,b)((a)-floor((a)/(b))*(b))
#define luai_numpow(a,b)(pow(a,b))
#define luai_numunm(a)(-(a))
#define luai_numeq(a,b)((a)==(b))
#define luai_numlt(a,b)((a)<(b))
#define luai_numle(a,b)((a)<=(b))
#define luai_numisnan(a)(!luai_numeq((a),(a)))
#define lua_number2int(i,d)((i)=(int)(d))
#define lua_number2integer(i,d)((i)=(lua_Integer)(d))
#define LUAI_THROW(L,c)longjmp((c)->b,1)
#define LUAI_TRY(L,c,a)if(setjmp((c)->b)==0){a}
#define lua_pclose(L,file)((void)((void)L,file),0)
#define lua_upvalueindex(i)((-10002)-(i))
typedef struct lua_State lua_State;
typedef int (*lua_CFunction)(lua_State * L);
typedef const char *(*lua_Reader)(lua_State * L, void *ud, size_t *sz);
typedef void *(*lua_Alloc)(void *ud, void *ptr, size_t osize, size_t nsize);
typedef double lua_Number;
typedef ptrdiff_t lua_Integer;
static void lua_settop(lua_State * L, int idx);
static int lua_type(lua_State * L, int idx);
static const char *lua_tolstring(lua_State * L, int idx, size_t *len);
static size_t lua_objlen(lua_State * L, int idx);
static void lua_pushlstring(lua_State * L, const char *s, size_t l);
static void lua_pushcclosure(lua_State * L, lua_CFunction fn, int n);
static void lua_createtable(lua_State * L, int narr, int nrec);
static void lua_setfield(lua_State * L, int idx, const char *k);
#define lua_pop(L,n)lua_settop(L,-(n)-1)
#define lua_newtable(L)lua_createtable(L,0,0)
#define lua_pushcfunction(L,f)lua_pushcclosure(L,(f),0)
#define lua_strlen(L,i)lua_objlen(L,(i))
#define lua_isfunction(L,n)(lua_type(L,(n))==6)
#define lua_istable(L,n)(lua_type(L,(n))==5)
#define lua_isnil(L,n)(lua_type(L,(n))==0)
#define lua_isboolean(L,n)(lua_type(L,(n))==1)
#define lua_isnone(L,n)(lua_type(L,(n))==(-1))
#define lua_isnoneornil(L,n)(lua_type(L,(n))<=0)
#define lua_pushliteral(L,s)lua_pushlstring(L,""s,(sizeof(s)/sizeof(char))-1)
#define lua_setglobal(L,s)lua_setfield(L,(-10002),(s))
#define lua_tostring(L,i)lua_tolstring(L,(i),NULL)
typedef struct lua_Debug lua_Debug;
typedef void (*lua_Hook)(lua_State * L, lua_Debug * ar);
struct lua_Debug {
	int event;
	const char *name;
	const char *namewhat;
	const char *what;
	const char *source;
	int currentline;
	int nups;
	int linedefined;
	int lastlinedefined;
	char short_src[60];
	int i_ci;
};
typedef unsigned int lu_int32;
typedef size_t lu_mem;
typedef ptrdiff_t l_mem;
typedef unsigned char lu_byte;
#define IntPoint(p)((unsigned int)(lu_mem)(p))
typedef union {
	double u;
	void *s;
	long l;
} L_Umaxalign;
typedef double l_uacNumber;
#define check_exp(c,e)(e)
#define UNUSED(x)((void)(x))
#define cast(t,exp)((t)(exp))
#define cast_byte(i)cast(lu_byte,(i))
#define cast_num(i)cast(lua_Number,(i))
#define cast_int(i)cast(int,(i))
typedef lu_int32 Instruction;
#define condhardstacktests(x)((void)0)
typedef union GCObject GCObject;
typedef struct GCheader {
	GCObject *next;
	lu_byte tt;
	lu_byte marked;
} GCheader;
typedef union {
	GCObject *gc;
	void *p;
	lua_Number n;
	int b;
} Value;
typedef struct lua_TValue {
	Value value;
	int tt;
} TValue;
#define ttisnil(o)(ttype(o)==0)
#define ttisnumber(o)(ttype(o)==3)
#define ttisstring(o)(ttype(o)==4)
#define ttistable(o)(ttype(o)==5)
#define ttisfunction(o)(ttype(o)==6)
#define ttisboolean(o)(ttype(o)==1)
#define ttisuserdata(o)(ttype(o)==7)
#define ttisthread(o)(ttype(o)==8)
#define ttislightuserdata(o)(ttype(o)==2)
#define ttype(o)((o)->tt)
#define gcvalue(o)check_exp(iscollectable(o),(o)->value.gc)
#define pvalue(o)check_exp(ttislightuserdata(o),(o)->value.p)
#define nvalue(o)check_exp(ttisnumber(o),(o)->value.n)
#define rawtsvalue(o)check_exp(ttisstring(o),&(o)->value.gc->ts)
#define tsvalue(o)(&rawtsvalue(o)->tsv)
#define rawuvalue(o)check_exp(ttisuserdata(o),&(o)->value.gc->u)
#define uvalue(o)(&rawuvalue(o)->uv)
#define clvalue(o)check_exp(ttisfunction(o),&(o)->value.gc->cl)
#define hvalue(o)check_exp(ttistable(o),&(o)->value.gc->h)
#define bvalue(o)check_exp(ttisboolean(o),(o)->value.b)
#define thvalue(o)check_exp(ttisthread(o),&(o)->value.gc->th)
#define l_isfalse(o)(ttisnil(o)||(ttisboolean(o)&&bvalue(o)==0))
#define checkconsistency(obj)
#define checkliveness(g,obj)
#define setnilvalue(obj)((obj)->tt=0)
#define setnvalue(obj,x){TValue*i_o=(obj);i_o->value.n=(x);i_o->tt=3;}
#define setbvalue(obj,x){TValue*i_o=(obj);i_o->value.b=(x);i_o->tt=1;}
#define setsvalue(L,obj,x){TValue*i_o=(obj);i_o->value.gc=cast(GCObject*,(x));i_o->tt=4;checkliveness(G(L),i_o);}
#define setuvalue(L,obj,x){TValue*i_o=(obj);i_o->value.gc=cast(GCObject*,(x));i_o->tt=7;checkliveness(G(L),i_o);}
#define setthvalue(L,obj,x){TValue*i_o=(obj);i_o->value.gc=cast(GCObject*,(x));i_o->tt=8;checkliveness(G(L),i_o);}
#define setclvalue(L,obj,x){TValue*i_o=(obj);i_o->value.gc=cast(GCObject*,(x));i_o->tt=6;checkliveness(G(L),i_o);}
#define sethvalue(L,obj,x){TValue*i_o=(obj);i_o->value.gc=cast(GCObject*,(x));i_o->tt=5;checkliveness(G(L),i_o);}
#define setptvalue(L,obj,x){TValue*i_o=(obj);i_o->value.gc=cast(GCObject*,(x));i_o->tt=(8+1);checkliveness(G(L),i_o);}
#define setobj(L,obj1,obj2){const TValue*o2=(obj2);TValue*o1=(obj1);o1->value=o2->value;o1->tt=o2->tt;checkliveness(G(L),o1);}
#define setttype(obj,tt)(ttype(obj)=(tt))
#define iscollectable(o)(ttype(o)>=4)
typedef TValue *StkId;
typedef union TString {
	L_Umaxalign dummy;
	struct {
		GCObject *next;
		lu_byte tt;
		lu_byte marked;
		lu_byte reserved;
		unsigned int hash;
		size_t len;
	} tsv;
} TString;
#define getstr(ts)cast(const char*,(ts)+1)
#define svalue(o)getstr(rawtsvalue(o))
typedef union Udata {
	L_Umaxalign dummy;
	struct {
		GCObject *next;
		lu_byte tt;
		lu_byte marked;
		struct Table *metatable;
		struct Table *env;
		size_t len;
	} uv;
} Udata;
typedef struct Proto {
	GCObject *next;
	lu_byte tt;
	lu_byte marked;
	TValue *k;
	Instruction *code;
	struct Proto **p;
	int *lineinfo;
	struct LocVar *locvars;
	TString **upvalues;
	TString *source;
	int sizeupvalues;
	int sizek;
	int sizecode;
	int sizelineinfo;
	int sizep;
	int sizelocvars;
	int linedefined;
	int lastlinedefined;
	GCObject *gclist;
	lu_byte nups;
	lu_byte numparams;
	lu_byte is_vararg;
	lu_byte maxstacksize;
} Proto;
typedef struct LocVar {
	TString *varname;
	int startpc;
	int endpc;
} LocVar;
typedef struct UpVal {
	GCObject *next;
	lu_byte tt;
	lu_byte marked;
	TValue *v;
	union {
		TValue value;
		struct {
			struct UpVal *prev;
			struct UpVal *next;
		} l;
	} u;
} UpVal;
typedef struct CClosure {
	GCObject *next;
	lu_byte tt;
	lu_byte marked;
	lu_byte isC;
	lu_byte nupvalues;
	GCObject *gclist;
	struct Table *env;
	lua_CFunction f;
	TValue upvalue[1];
} CClosure;
typedef struct LClosure {
	GCObject *next;
	lu_byte tt;
	lu_byte marked;
	lu_byte isC;
	lu_byte nupvalues;
	GCObject *gclist;
	struct Table *env;
	struct Proto *p;
	UpVal *upvals[1];
} LClosure;
typedef union Closure {
	CClosure c;
	LClosure l;
} Closure;
#define iscfunction(o)(ttype(o)==6&&clvalue(o)->c.isC)
typedef union TKey {
	struct {
		Value value;
		int tt;
		struct Node *next;
	} nk;
	TValue tvk;
} TKey;
typedef struct Node {
	TValue i_val;
	TKey i_key;
} Node;
typedef struct Table {
	GCObject *next;
	lu_byte tt;
	lu_byte marked;
	lu_byte flags;
	lu_byte lsizenode;
	struct Table *metatable;
	TValue *array;
	Node *node;
	Node *lastfree;
	GCObject *gclist;
	int sizearray;
} Table;
#define lmod(s,size)(check_exp((size&(size-1))==0,(cast(int,(s)&((size)-1)))))
#define twoto(x)((size_t)1<<(x))
#define sizenode(t)(twoto((t)->lsizenode))
static const TValue luaO_nilobject_;
#define ceillog2(x)(luaO_log2((x)-1)+1)
static int luaO_log2(unsigned int x);
#define gfasttm(g,et,e)((et)==NULL?NULL:((et)->flags&(1u<<(e)))?NULL:luaT_gettm(et,e,(g)->tmname[e]))
#define fasttm(l,et,e)gfasttm(G(l),et,e)
static const TValue *luaT_gettm(Table * events, TMS event, TString * ename);
#define luaM_reallocv(L,b,on,n,e)((cast(size_t,(n)+1)<=((size_t)(~(size_t)0)-2)/(e))?luaM_realloc_(L,(b),(on)*(e),(n)*(e)):luaM_toobig(L))
#define luaM_freemem(L,b,s)luaM_realloc_(L,(b),(s),0)
#define luaM_free(L,b)luaM_realloc_(L,(b),sizeof(*(b)),0)
#define luaM_freearray(L,b,n,t)luaM_reallocv(L,(b),n,0,sizeof(t))
#define luaM_malloc(L,t)luaM_realloc_(L,NULL,0,(t))
#define luaM_new(L,t)cast(t*,luaM_malloc(L,sizeof(t)))
#define luaM_newvector(L,n,t)cast(t*,luaM_reallocv(L,NULL,0,n,sizeof(t)))
#define luaM_growvector(L,v,nelems,size,t,limit,e)if((nelems)+1>(size))((v)=cast(t*,luaM_growaux_(L,v,&(size),sizeof(t),limit,e)))
#define luaM_reallocvector(L,v,oldn,n,t)((v)=cast(t*,luaM_reallocv(L,v,oldn,n,sizeof(t))))
static void *luaM_realloc_(lua_State * L, void *block, size_t oldsize,
			   size_t size);
static void *luaM_toobig(lua_State * L);
static void *luaM_growaux_(lua_State * L, void *block, int *size,
			   size_t size_elem, int limit, const char *errormsg);
typedef struct Zio ZIO;
#define char2int(c)cast(int,cast(unsigned char,(c)))
#define zgetc(z)(((z)->n--)>0?char2int(*(z)->p++):luaZ_fill(z))
typedef struct Mbuffer {
	char *buffer;
	size_t n;
	size_t buffsize;
} Mbuffer;
#define luaZ_initbuffer(L,buff)((buff)->buffer=NULL,(buff)->buffsize=0)
#define luaZ_buffer(buff)((buff)->buffer)
#define luaZ_sizebuffer(buff)((buff)->buffsize)
#define luaZ_bufflen(buff)((buff)->n)
#define luaZ_resetbuffer(buff)((buff)->n=0)
#define luaZ_resizebuffer(L,buff,size)(luaM_reallocvector(L,(buff)->buffer,(buff)->buffsize,size,char),(buff)->buffsize=size)
#define luaZ_freebuffer(L,buff)luaZ_resizebuffer(L,buff,0)
struct Zio {
	size_t n;
	const char *p;
	lua_Reader reader;
	void *data;
	lua_State *L;
};
static int luaZ_fill(ZIO * z);
struct lua_longjmp;
#define gt(L)(&L->l_gt)
#define registry(L)(&G(L)->l_registry)
typedef struct stringtable {
	GCObject **hash;
	lu_int32 nuse;
	int size;
} stringtable;
typedef struct CallInfo {
	StkId base;
	StkId func;
	StkId top;
	const Instruction *savedpc;
	int nresults;
	int tailcalls;
} CallInfo;
#define curr_func(L)(clvalue(L->ci->func))
#define ci_func(ci)(clvalue((ci)->func))
#define f_isLua(ci)(!ci_func(ci)->c.isC)
#define isLua(ci)(ttisfunction((ci)->func)&&f_isLua(ci))
typedef struct global_State {
	stringtable strt;
	lua_Alloc frealloc;
	void *ud;
	lu_byte currentwhite;
	lu_byte gcstate;
	int sweepstrgc;
	GCObject *rootgc;
	GCObject **sweepgc;
	GCObject *gray;
	GCObject *grayagain;
	GCObject *weak;
	GCObject *tmudata;
	Mbuffer buff;
	lu_mem GCthreshold;
	lu_mem totalbytes;
	lu_mem estimate;
	lu_mem gcdept;
	int gcpause;
	int gcstepmul;
	lua_CFunction panic;
	TValue l_registry;
	struct lua_State *mainthread;
	UpVal uvhead;
	struct Table *mt[(8 + 1)];
	TString *tmname[TM_N];
} global_State;
struct lua_State {
	GCObject *next;
	lu_byte tt;
	lu_byte marked;
	lu_byte status;
	StkId top;
	StkId base;
	global_State *l_G;
	CallInfo *ci;
	const Instruction *savedpc;
	StkId stack_last;
	StkId stack;
	CallInfo *end_ci;
	CallInfo *base_ci;
	int stacksize;
	int size_ci;
	unsigned short nCcalls;
	unsigned short baseCcalls;
	lu_byte hookmask;
	lu_byte allowhook;
	int basehookcount;
	int hookcount;
	lua_Hook hook;
	TValue l_gt;
	TValue env;
	GCObject *openupval;
	GCObject *gclist;
	struct lua_longjmp *errorJmp;
	ptrdiff_t errfunc;
};
#define G(L)(L->l_G)
union GCObject {
	GCheader gch;
	union TString ts;
	union Udata u;
	union Closure cl;
	struct Table h;
	struct Proto p;
	struct UpVal uv;
	struct lua_State th;
};
#define rawgco2ts(o)check_exp((o)->gch.tt==4,&((o)->ts))
#define gco2ts(o)(&rawgco2ts(o)->tsv)
#define rawgco2u(o)check_exp((o)->gch.tt==7,&((o)->u))
#define gco2u(o)(&rawgco2u(o)->uv)
#define gco2cl(o)check_exp((o)->gch.tt==6,&((o)->cl))
#define gco2h(o)check_exp((o)->gch.tt==5,&((o)->h))
#define gco2p(o)check_exp((o)->gch.tt==(8+1),&((o)->p))
#define gco2uv(o)check_exp((o)->gch.tt==(8+2),&((o)->uv))
#define ngcotouv(o)check_exp((o)==NULL||(o)->gch.tt==(8+2),&((o)->uv))
#define gco2th(o)check_exp((o)->gch.tt==8,&((o)->th))
#define obj2gco(v)(cast(GCObject*,(v)))
static void luaE_freethread(lua_State * L, lua_State * L1);
#define pcRel(pc,p)(cast(int,(pc)-(p)->code)-1)
#define getline_(f,pc)(((f)->lineinfo)?(f)->lineinfo[pc]:0)
#define resethookcount(L)(L->hookcount=L->basehookcount)
static void luaG_typeerror(lua_State * L, const TValue * o, const char *opname);
static void luaG_runerror(lua_State * L, const char *fmt, ...);
#define luaD_checkstack(L,n)if((char*)L->stack_last-(char*)L->top<=(n)*(int)sizeof(TValue))luaD_growstack(L,n);else condhardstacktests(luaD_reallocstack(L,L->stacksize-5-1));
#define incr_top(L){luaD_checkstack(L,1);L->top++;}
#define savestack(L,p)((char*)(p)-(char*)L->stack)
#define restorestack(L,n)((TValue*)((char*)L->stack+(n)))
#define saveci(L,p)((char*)(p)-(char*)L->base_ci)
#define restoreci(L,n)((CallInfo*)((char*)L->base_ci+(n)))
typedef void (*Pfunc)(lua_State * L, void *ud);
static int luaD_poscall(lua_State * L, StkId firstResult);
static void luaD_reallocCI(lua_State * L, int newsize);
static void luaD_reallocstack(lua_State * L, int newsize);
static void luaD_growstack(lua_State * L, int n);
static void luaD_throw(lua_State * L, int errcode);
static void *luaM_growaux_(lua_State * L, void *block, int *size,
			   size_t size_elems, int limit, const char *errormsg)
{
	void *newblock;
	int newsize;
	if (*size >= limit / 2) {
		if (*size >= limit)
			luaG_runerror(L, errormsg);
		newsize = limit;
	} else {
		newsize = (*size) * 2;
		if (newsize < 4)
			newsize = 4;
	}
	newblock = luaM_reallocv(L, block, *size, newsize, size_elems);
	*size = newsize;
	return newblock;
}

static void *luaM_toobig(lua_State * L)
{
	luaG_runerror(L, "memory allocation error: block too big");
	return NULL;
}

static void *luaM_realloc_(lua_State * L, void *block, size_t osize,
			   size_t nsize)
{
	global_State *g = G(L);
	block = (*g->frealloc) (g->ud, block, osize, nsize);
	if (block == NULL && nsize > 0)
		luaD_throw(L, 4);
	g->totalbytes = (g->totalbytes - osize) + nsize;
	return block;
}

#define resetbits(x,m)((x)&=cast(lu_byte,~(m)))
#define setbits(x,m)((x)|=(m))
#define testbits(x,m)((x)&(m))
#define bitmask(b)(1<<(b))
#define bit2mask(b1,b2)(bitmask(b1)|bitmask(b2))
#define l_setbit(x,b)setbits(x,bitmask(b))
#define resetbit(x,b)resetbits(x,bitmask(b))
#define testbit(x,b)testbits(x,bitmask(b))
#define set2bits(x,b1,b2)setbits(x,(bit2mask(b1,b2)))
#define reset2bits(x,b1,b2)resetbits(x,(bit2mask(b1,b2)))
#define test2bits(x,b1,b2)testbits(x,(bit2mask(b1,b2)))
#define iswhite(x)test2bits((x)->gch.marked,0,1)
#define isblack(x)testbit((x)->gch.marked,2)
#define isgray(x)(!isblack(x)&&!iswhite(x))
#define otherwhite(g)(g->currentwhite^bit2mask(0,1))
#define isdead(g,v)((v)->gch.marked&otherwhite(g)&bit2mask(0,1))
#define changewhite(x)((x)->gch.marked^=bit2mask(0,1))
#define gray2black(x)l_setbit((x)->gch.marked,2)
#define valiswhite(x)(iscollectable(x)&&iswhite(gcvalue(x)))
#define luaC_white(g)cast(lu_byte,(g)->currentwhite&bit2mask(0,1))
#define luaC_checkGC(L){condhardstacktests(luaD_reallocstack(L,L->stacksize-5-1));if(G(L)->totalbytes>=G(L)->GCthreshold)luaC_step(L);}
#define luaC_barrier(L,p,v){if(valiswhite(v)&&isblack(obj2gco(p)))luaC_barrierf(L,obj2gco(p),gcvalue(v));}
#define luaC_barriert(L,t,v){if(valiswhite(v)&&isblack(obj2gco(t)))luaC_barrierback(L,t);}
#define luaC_objbarrier(L,p,o){if(iswhite(obj2gco(o))&&isblack(obj2gco(p)))luaC_barrierf(L,obj2gco(p),obj2gco(o));}
#define luaC_objbarriert(L,t,o){if(iswhite(obj2gco(o))&&isblack(obj2gco(t)))luaC_barrierback(L,t);}
static void luaC_step(lua_State * L);
static void luaC_link(lua_State * L, GCObject * o, lu_byte tt);
static void luaC_linkupval(lua_State * L, UpVal * uv);
static void luaC_barrierf(lua_State * L, GCObject * o, GCObject * v);
static void luaC_barrierback(lua_State * L, Table * t);
#define sizestring(s)(sizeof(union TString)+((s)->len+1)*sizeof(char))
#define sizeudata(u)(sizeof(union Udata)+(u)->len)
#define luaS_new(L,s)(luaS_newlstr(L,s,strlen(s)))
#define luaS_newliteral(L,s)(luaS_newlstr(L,""s,(sizeof(s)/sizeof(char))-1))
#define luaS_fix(s)l_setbit((s)->tsv.marked,5)
static TString *luaS_newlstr(lua_State * L, const char *str, size_t l);
#define tostring(L,o)((ttype(o)==4)||(luaV_tostring(L,o)))
#define tonumber(o,n)(ttype(o)==3||(((o)=luaV_tonumber(o,n))!=NULL))
#define equalobj(L,o1,o2)(ttype(o1)==ttype(o2)&&luaV_equalval(L,o1,o2))
static int luaV_equalval(lua_State * L, const TValue * t1, const TValue * t2);
static const TValue *luaV_tonumber(const TValue * obj, TValue * n);
static int luaV_tostring(lua_State * L, StkId obj);
static void luaV_execute(lua_State * L, int nexeccalls);
static void luaV_concat(lua_State * L, int total, int last);
static const TValue luaO_nilobject_ = { {NULL}, 0 };

static int luaO_int2fb(unsigned int x)
{
	int e = 0;
	while (x >= 16) {
		x = (x + 1) >> 1;
		e++;
	}
	if (x < 8)
		return x;
	else
		return ((e + 1) << 3) | (cast_int(x) - 8);
}

static int luaO_fb2int(int x)
{
	int e = (x >> 3) & 31;
	if (e == 0)
		return x;
	else
		return ((x & 7) + 8) << (e - 1);
}

static int luaO_log2(unsigned int x)
{
	static const lu_byte log_2[256] = {
		0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
		    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
		6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
		    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
		    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
		    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
		8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
		    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
		8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
		    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
		8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
		    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
		8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
		    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
	};
	int l = -1;
	while (x >= 256) {
		l += 8;
		x >>= 8;
	}
	return l + log_2[x];
}

static int luaO_rawequalObj(const TValue * t1, const TValue * t2)
{
	if (ttype(t1) != ttype(t2))
		return 0;
	else
		switch (ttype(t1)) {
		case 0:
			return 1;
		case 3:
			return luai_numeq(nvalue(t1), nvalue(t2));
		case 1:
			return bvalue(t1) == bvalue(t2);
		case 2:
			return pvalue(t1) == pvalue(t2);
		default:
			return gcvalue(t1) == gcvalue(t2);
		}
}

static int luaO_str2d(const char *s, lua_Number * result)
{
	char *endptr;
	*result = lua_str2number(s, &endptr);
	if (endptr == s)
		return 0;
	if (*endptr == 'x' || *endptr == 'X')
		*result = cast_num(strtoul(s, &endptr, 16));
	if (*endptr == '\0')
		return 1;
	while (isspace(cast(unsigned char, *endptr)))
		 endptr++;
	if (*endptr != '\0')
		return 0;
	return 1;
}

static void pushstr(lua_State * L, const char *str)
{
	setsvalue(L, L->top, luaS_new(L, str));
	incr_top(L);
}

static const char *luaO_pushvfstring(lua_State * L, const char *fmt,
				     va_list argp)
{
	int n = 1;
	pushstr(L, "");
	for (;;) {
		const char *e = strchr(fmt, '%');
		if (e == NULL)
			break;
		setsvalue(L, L->top, luaS_newlstr(L, fmt, e - fmt));
		incr_top(L);
		switch (*(e + 1)) {
		case 's':{
				const char *s = va_arg(argp, char *);
				if (s == NULL)
					s = "(null)";
				pushstr(L, s);
				break;
			}
		case 'c':{
				char buff[2];
				buff[0] = cast(char, va_arg(argp, int));
				buff[1] = '\0';
				pushstr(L, buff);
				break;
			}
		case 'd':{
				setnvalue(L->top, cast_num(va_arg(argp, int)));
				incr_top(L);
				break;
			}
		case 'f':{
				setnvalue(L->top,
					  cast_num(va_arg(argp, l_uacNumber)));
				incr_top(L);
				break;
			}
		case 'p':{
				char buff[4 * sizeof(void *) + 8];
				sprintf(buff, "%p", va_arg(argp, void *));
				pushstr(L, buff);
				break;
			}
		case '%':{
				pushstr(L, "%");
				break;
			}
		default:{
				char buff[3];
				buff[0] = '%';
				buff[1] = *(e + 1);
				buff[2] = '\0';
				pushstr(L, buff);
				break;
			}
		}
		n += 2;
		fmt = e + 2;
	}
	pushstr(L, fmt);
	luaV_concat(L, n + 1, cast_int(L->top - L->base) - 1);
	L->top -= n;
	return svalue(L->top - 1);
}

static const char *luaO_pushfstring(lua_State * L, const char *fmt, ...)
{
	const char *msg;
	va_list argp;
	va_start(argp, fmt);
	msg = luaO_pushvfstring(L, fmt, argp);
	va_end(argp);
	return msg;
}

static void luaO_chunkid(char *out, const char *source, size_t bufflen)
{
	if (*source == '=') {
		strncpy(out, source + 1, bufflen);
		out[bufflen - 1] = '\0';
	} else {
		if (*source == '@') {
			size_t l;
			source++;
			bufflen -= sizeof(" '...' ");
			l = strlen(source);
			strcpy(out, "");
			if (l > bufflen) {
				source += (l - bufflen);
				strcat(out, "...");
			}
			strcat(out, source);
		} else {
			size_t len = strcspn(source, "\n\r");
			bufflen -= sizeof(" [string \"...\"] ");
			if (len > bufflen)
				len = bufflen;
			strcpy(out, "[string \"");
			if (source[len] != '\0') {
				strncat(out, source, len);
				strcat(out, "...");
			} else
				strcat(out, source);
			strcat(out, "\"]");
		}
	}
}

#define gnode(t,i)(&(t)->node[i])
#define gkey(n)(&(n)->i_key.nk)
#define gval(n)(&(n)->i_val)
#define gnext(n)((n)->i_key.nk.next)
#define key2tval(n)(&(n)->i_key.tvk)
static TValue *luaH_setnum(lua_State * L, Table * t, int key);
static const TValue *luaH_getstr(Table * t, TString * key);
static TValue *luaH_set(lua_State * L, Table * t, const TValue * key);
static const char *const luaT_typenames[] = {
	"nil", "boolean", "userdata", "number",
	"string", "table", "function", "userdata", "thread",
	"proto", "upval"
};

static void luaT_init(lua_State * L)
{
	static const char *const luaT_eventname[] = {
		"__index", "__newindex",
		"__gc", "__mode", "__eq",
		"__add", "__sub", "__mul", "__div", "__mod",
		"__pow", "__unm", "__len", "__lt", "__le",
		"__concat", "__call"
	};
	int i;
	for (i = 0; i < TM_N; i++) {
		G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
		luaS_fix(G(L)->tmname[i]);
	}
}

static const TValue *luaT_gettm(Table * events, TMS event, TString * ename)
{
	const TValue *tm = luaH_getstr(events, ename);
	if (ttisnil(tm)) {
		events->flags |= cast_byte(1u << event);
		return NULL;
	} else
		return tm;
}

static const TValue *luaT_gettmbyobj(lua_State * L, const TValue * o, TMS event)
{
	Table *mt;
	switch (ttype(o)) {
	case 5:
		mt = hvalue(o)->metatable;
		break;
	case 7:
		mt = uvalue(o)->metatable;
		break;
	default:
		mt = G(L)->mt[ttype(o)];
	}
	return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : (&luaO_nilobject_));
}

#define sizeCclosure(n)(cast(int,sizeof(CClosure))+cast(int,sizeof(TValue)*((n)-1)))
#define sizeLclosure(n)(cast(int,sizeof(LClosure))+cast(int,sizeof(TValue*)*((n)-1)))
static Closure *luaF_newCclosure(lua_State * L, int nelems, Table * e)
{
	Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
	luaC_link(L, obj2gco(c), 6);
	c->c.isC = 1;
	c->c.env = e;
	c->c.nupvalues = cast_byte(nelems);
	return c;
}

static Closure *luaF_newLclosure(lua_State * L, int nelems, Table * e)
{
	Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
	luaC_link(L, obj2gco(c), 6);
	c->l.isC = 0;
	c->l.env = e;
	c->l.nupvalues = cast_byte(nelems);
	while (nelems--)
		c->l.upvals[nelems] = NULL;
	return c;
}

static UpVal *luaF_newupval(lua_State * L)
{
	UpVal *uv = luaM_new(L, UpVal);
	luaC_link(L, obj2gco(uv), (8 + 2));
	uv->v = &uv->u.value;
	setnilvalue(uv->v);
	return uv;
}

static UpVal *luaF_findupval(lua_State * L, StkId level)
{
	global_State *g = G(L);
	GCObject **pp = &L->openupval;
	UpVal *p;
	UpVal *uv;
	while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) {
		if (p->v == level) {
			if (isdead(g, obj2gco(p)))
				changewhite(obj2gco(p));
			return p;
		}
		pp = &p->next;
	}
	uv = luaM_new(L, UpVal);
	uv->tt = (8 + 2);
	uv->marked = luaC_white(g);
	uv->v = level;
	uv->next = *pp;
	*pp = obj2gco(uv);
	uv->u.l.prev = &g->uvhead;
	uv->u.l.next = g->uvhead.u.l.next;
	uv->u.l.next->u.l.prev = uv;
	g->uvhead.u.l.next = uv;
	return uv;
}

static void unlinkupval(UpVal * uv)
{
	uv->u.l.next->u.l.prev = uv->u.l.prev;
	uv->u.l.prev->u.l.next = uv->u.l.next;
}

static void luaF_freeupval(lua_State * L, UpVal * uv)
{
	if (uv->v != &uv->u.value)
		unlinkupval(uv);
	luaM_free(L, uv);
}

static void luaF_close(lua_State * L, StkId level)
{
	UpVal *uv;
	global_State *g = G(L);
	while (L->openupval != NULL
	       && (uv = ngcotouv(L->openupval))->v >= level) {
		GCObject *o = obj2gco(uv);
		L->openupval = uv->next;
		if (isdead(g, o))
			luaF_freeupval(L, uv);
		else {
			unlinkupval(uv);
			setobj(L, &uv->u.value, uv->v);
			uv->v = &uv->u.value;
			luaC_linkupval(L, uv);
		}
	}
}

static Proto *luaF_newproto(lua_State * L)
{
	Proto *f = luaM_new(L, Proto);
	luaC_link(L, obj2gco(f), (8 + 1));
	f->k = NULL;
	f->sizek = 0;
	f->p = NULL;
	f->sizep = 0;
	f->code = NULL;
	f->sizecode = 0;
	f->sizelineinfo = 0;
	f->sizeupvalues = 0;
	f->nups = 0;
	f->upvalues = NULL;
	f->numparams = 0;
	f->is_vararg = 0;
	f->maxstacksize = 0;
	f->lineinfo = NULL;
	f->sizelocvars = 0;
	f->locvars = NULL;
	f->linedefined = 0;
	f->lastlinedefined = 0;
	f->source = NULL;
	return f;
}

static void luaF_freeproto(lua_State * L, Proto * f)
{
	luaM_freearray(L, f->code, f->sizecode, Instruction);
	luaM_freearray(L, f->p, f->sizep, Proto *);
	luaM_freearray(L, f->k, f->sizek, TValue);
	luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
	luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
	luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
	luaM_free(L, f);
}

static void luaF_freeclosure(lua_State * L, Closure * c)
{
	int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
	    sizeLclosure(c->l.nupvalues);
	luaM_freemem(L, c, size);
}

#define MASK1(n,p)((~((~(Instruction)0)<<n))<<p)
#define MASK0(n,p)(~MASK1(n,p))
#define GET_OPCODE(i)(cast(OpCode,((i)>>0)&MASK1(6,0)))
#define SET_OPCODE(i,o)((i)=(((i)&MASK0(6,0))|((cast(Instruction,o)<<0)&MASK1(6,0))))
#define GETARG_A(i)(cast(int,((i)>>(0+6))&MASK1(8,0)))
#define SETARG_A(i,u)((i)=(((i)&MASK0(8,(0+6)))|((cast(Instruction,u)<<(0+6))&MASK1(8,(0+6)))))
#define GETARG_B(i)(cast(int,((i)>>(((0+6)+8)+9))&MASK1(9,0)))
#define SETARG_B(i,b)((i)=(((i)&MASK0(9,(((0+6)+8)+9)))|((cast(Instruction,b)<<(((0+6)+8)+9))&MASK1(9,(((0+6)+8)+9)))))
#define GETARG_C(i)(cast(int,((i)>>((0+6)+8))&MASK1(9,0)))
#define SETARG_C(i,b)((i)=(((i)&MASK0(9,((0+6)+8)))|((cast(Instruction,b)<<((0+6)+8))&MASK1(9,((0+6)+8)))))
#define GETARG_Bx(i)(cast(int,((i)>>((0+6)+8))&MASK1((9+9),0)))
#define SETARG_Bx(i,b)((i)=(((i)&MASK0((9+9),((0+6)+8)))|((cast(Instruction,b)<<((0+6)+8))&MASK1((9+9),((0+6)+8)))))
#define GETARG_sBx(i)(GETARG_Bx(i)-(((1<<(9+9))-1)>>1))
#define SETARG_sBx(i,b)SETARG_Bx((i),cast(unsigned int,(b)+(((1<<(9+9))-1)>>1)))
#define CREATE_ABC(o,a,b,c)((cast(Instruction,o)<<0)|(cast(Instruction,a)<<(0+6))|(cast(Instruction,b)<<(((0+6)+8)+9))|(cast(Instruction,c)<<((0+6)+8)))
#define CREATE_ABx(o,a,bc)((cast(Instruction,o)<<0)|(cast(Instruction,a)<<(0+6))|(cast(Instruction,bc)<<((0+6)+8)))
#define ISK(x)((x)&(1<<(9-1)))
#define INDEXK(r)((int)(r)&~(1<<(9-1)))
#define RKASK(x)((x)|(1<<(9-1)))
static const lu_byte luaP_opmodes[(cast(int, OP_VARARG) + 1)];
#define getBMode(m)(cast(enum OpArgMask,(luaP_opmodes[m]>>4)&3))
#define getCMode(m)(cast(enum OpArgMask,(luaP_opmodes[m]>>2)&3))
#define testTMode(m)(luaP_opmodes[m]&(1<<7))
typedef struct expdesc {
	expkind k;
	union {
		struct {
			int info, aux;
		} s;
		lua_Number nval;
	} u;
	int t;
	int f;
} expdesc;
typedef struct upvaldesc {
	lu_byte k;
	lu_byte info;
} upvaldesc;
struct BlockCnt;
typedef struct FuncState {
	Proto *f;
	Table *h;
	struct FuncState *prev;
	struct LexState *ls;
	struct lua_State *L;
	struct BlockCnt *bl;
	int pc;
	int lasttarget;
	int jpc;
	int freereg;
	int nk;
	int np;
	short nlocvars;
	lu_byte nactvar;
	upvaldesc upvalues[60];
	unsigned short actvar[200];
} FuncState;
static Proto *luaY_parser(lua_State * L, ZIO * z, Mbuffer * buff,
			  const char *name);
struct lua_longjmp {
	struct lua_longjmp *previous;
	jmp_buf b;
	volatile int status;
};
static void luaD_seterrorobj(lua_State * L, int errcode, StkId oldtop)
{
	switch (errcode) {
	case 4:{
			setsvalue(L, oldtop,
				  luaS_newliteral(L, "not enough memory"));
			break;
		}
	case 5:{
			setsvalue(L, oldtop,
				  luaS_newliteral(L,
						  "error in error handling"));
			break;
		}
	case 3:
	case 2:{
			setobj(L, oldtop, L->top - 1);
			break;
		}
	}
	L->top = oldtop + 1;
}

static void restore_stack_limit(lua_State * L)
{
	if (L->size_ci > 20000) {
		int inuse = cast_int(L->ci - L->base_ci);
		if (inuse + 1 < 20000)
			luaD_reallocCI(L, 20000);
	}
}

static void resetstack(lua_State * L, int status)
{
	L->ci = L->base_ci;
	L->base = L->ci->base;
	luaF_close(L, L->base);
	luaD_seterrorobj(L, status, L->base);
	L->nCcalls = L->baseCcalls;
	L->allowhook = 1;
	restore_stack_limit(L);
	L->errfunc = 0;
	L->errorJmp = NULL;
}

static void luaD_throw(lua_State * L, int errcode)
{
	if (L->errorJmp) {
		L->errorJmp->status = errcode;
		LUAI_THROW(L, L->errorJmp);
	} else {
		L->status = cast_byte(errcode);
		if (G(L)->panic) {
			resetstack(L, errcode);
			G(L)->panic(L);
		}
		exit(EXIT_FAILURE);
	}
}

static int luaD_rawrunprotected(lua_State * L, Pfunc f, void *ud)
{
	struct lua_longjmp lj;
	lj.status = 0;
	lj.previous = L->errorJmp;
	L->errorJmp = &lj;
	LUAI_TRY(L, &lj, (*f) (L, ud););
	L->errorJmp = lj.previous;
	return lj.status;
}

static void correctstack(lua_State * L, TValue * oldstack)
{
	CallInfo *ci;
	GCObject *up;
	L->top = (L->top - oldstack) + L->stack;
	for (up = L->openupval; up != NULL; up = up->gch.next)
		gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
	for (ci = L->base_ci; ci <= L->ci; ci++) {
		ci->top = (ci->top - oldstack) + L->stack;
		ci->base = (ci->base - oldstack) + L->stack;
		ci->func = (ci->func - oldstack) + L->stack;
	}
	L->base = (L->base - oldstack) + L->stack;
}

static void luaD_reallocstack(lua_State * L, int newsize)
{
	TValue *oldstack = L->stack;
	int realsize = newsize + 1 + 5;
	luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);
	L->stacksize = realsize;
	L->stack_last = L->stack + newsize;
	correctstack(L, oldstack);
}

static void luaD_reallocCI(lua_State * L, int newsize)
{
	CallInfo *oldci = L->base_ci;
	luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
	L->size_ci = newsize;
	L->ci = (L->ci - oldci) + L->base_ci;
	L->end_ci = L->base_ci + L->size_ci - 1;
}

static void luaD_growstack(lua_State * L, int n)
{
	if (n <= L->stacksize)
		luaD_reallocstack(L, 2 * L->stacksize);
	else
		luaD_reallocstack(L, L->stacksize + n);
}

static CallInfo *growCI(lua_State * L)
{
	if (L->size_ci > 20000)
		luaD_throw(L, 5);
	else {
		luaD_reallocCI(L, 2 * L->size_ci);
		if (L->size_ci > 20000)
			luaG_runerror(L, "stack overflow");
	}
	return ++L->ci;
}

static StkId adjust_varargs(lua_State * L, Proto * p, int actual)
{
	int i;
	int nfixargs = p->numparams;
	Table *htab = NULL;
	StkId base, fixed;
	for (; actual < nfixargs; ++actual)
		setnilvalue(L->top++);
	fixed = L->top - actual;
	base = L->top;
	for (i = 0; i < nfixargs; i++) {
		setobj(L, L->top++, fixed + i);
		setnilvalue(fixed + i);
	}
	if (htab) {
		sethvalue(L, L->top++, htab);
	}
	return base;
}

static StkId tryfuncTM(lua_State * L, StkId func)
{
	const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
	StkId p;
	ptrdiff_t funcr = savestack(L, func);
	if (!ttisfunction(tm))
		luaG_typeerror(L, func, "call");
	for (p = L->top; p > func; p--)
		setobj(L, p, p - 1);
	incr_top(L);
	func = restorestack(L, funcr);
	setobj(L, func, tm);
	return func;
}

#define inc_ci(L)((L->ci==L->end_ci)?growCI(L):(condhardstacktests(luaD_reallocCI(L,L->size_ci)),++L->ci))
static int luaD_precall(lua_State * L, StkId func, int nresults)
{
	LClosure *cl;
	ptrdiff_t funcr;
	if (!ttisfunction(func))
		func = tryfuncTM(L, func);
	funcr = savestack(L, func);
	cl = &clvalue(func)->l;
	L->ci->savedpc = L->savedpc;
	if (!cl->isC) {
		CallInfo *ci;
		StkId st, base;
		Proto *p = cl->p;
		luaD_checkstack(L, p->maxstacksize);
		func = restorestack(L, funcr);
		if (!p->is_vararg) {
			base = func + 1;
			if (L->top > base + p->numparams)
				L->top = base + p->numparams;
		} else {
			int nargs = cast_int(L->top - func) - 1;
			base = adjust_varargs(L, p, nargs);
			func = restorestack(L, funcr);
		}
		ci = inc_ci(L);
		ci->func = func;
		L->base = ci->base = base;
		ci->top = L->base + p->maxstacksize;
		L->savedpc = p->code;
		ci->tailcalls = 0;
		ci->nresults = nresults;
		for (st = L->top; st < ci->top; st++)
			setnilvalue(st);
		L->top = ci->top;
		return 0;
	} else {
		CallInfo *ci;
		int n;
		luaD_checkstack(L, 20);
		ci = inc_ci(L);
		ci->func = restorestack(L, funcr);
		L->base = ci->base = ci->func + 1;
		ci->top = L->top + 20;
		ci->nresults = nresults;
		n = (*curr_func(L)->c.f) (L);
		if (n < 0)
			return 2;
		else {
			luaD_poscall(L, L->top - n);
			return 1;
		}
	}
}

static int luaD_poscall(lua_State * L, StkId firstResult)
{
	StkId res;
	int wanted, i;
	CallInfo *ci;
	ci = L->ci--;
	res = ci->func;
	wanted = ci->nresults;
	L->base = (ci - 1)->base;
	L->savedpc = (ci - 1)->savedpc;
	for (i = wanted; i != 0 && firstResult < L->top; i--)
		setobj(L, res++, firstResult++);
	while (i-- > 0)
		setnilvalue(res++);
	L->top = res;
	return (wanted - (-1));
}

static void luaD_call(lua_State * L, StkId func, int nResults)
{
	if (++L->nCcalls >= 200) {
		if (L->nCcalls == 200)
			luaG_runerror(L, "C stack overflow");
		else if (L->nCcalls >= (200 + (200 >> 3)))
			luaD_throw(L, 5);
	}
	if (luaD_precall(L, func, nResults) == 0)
		luaV_execute(L, 1);
	L->nCcalls--;
	luaC_checkGC(L);
}

static int luaD_pcall(lua_State * L, Pfunc func, void *u,
		      ptrdiff_t old_top, ptrdiff_t ef)
{
	int status;
	unsigned short oldnCcalls = L->nCcalls;
	ptrdiff_t old_ci = saveci(L, L->ci);
	lu_byte old_allowhooks = L->allowhook;
	ptrdiff_t old_errfunc = L->errfunc;
	L->errfunc = ef;
	status = luaD_rawrunprotected(L, func, u);
	if (status != 0) {
		StkId oldtop = restorestack(L, old_top);
		luaF_close(L, oldtop);
		luaD_seterrorobj(L, status, oldtop);
		L->nCcalls = oldnCcalls;
		L->ci = restoreci(L, old_ci);
		L->base = L->ci->base;
		L->savedpc = L->ci->savedpc;
		L->allowhook = old_allowhooks;
		restore_stack_limit(L);
	}
	L->errfunc = old_errfunc;
	return status;
}

struct SParser {
	ZIO *z;
	Mbuffer buff;
	const char *name;
};
static void f_parser(lua_State * L, void *ud)
{
	int i;
	Proto *tf;
	Closure *cl;
	struct SParser *p = cast(struct SParser *, ud);
	luaC_checkGC(L);
	tf = luaY_parser(L, p->z, &p->buff, p->name);
	cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
	cl->l.p = tf;
	for (i = 0; i < tf->nups; i++)
		cl->l.upvals[i] = luaF_newupval(L);
	setclvalue(L, L->top, cl);
	incr_top(L);
}

static int luaD_protectedparser(lua_State * L, ZIO * z, const char *name)
{
	struct SParser p;
	int status;
	p.z = z;
	p.name = name;
	luaZ_initbuffer(L, &p.buff);
	status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
	luaZ_freebuffer(L, &p.buff);
	return status;
}

static void luaS_resize(lua_State * L, int newsize)
{
	GCObject **newhash;
	stringtable *tb;
	int i;
	if (G(L)->gcstate == 2)
		return;
	newhash = luaM_newvector(L, newsize, GCObject *);
	tb = &G(L)->strt;
	for (i = 0; i < newsize; i++)
		newhash[i] = NULL;
	for (i = 0; i < tb->size; i++) {
		GCObject *p = tb->hash[i];
		while (p) {
			GCObject *next = p->gch.next;
			unsigned int h = gco2ts(p)->hash;
			int h1 = lmod(h, newsize);
			p->gch.next = newhash[h1];
			newhash[h1] = p;
			p = next;
		}
	}
	luaM_freearray(L, tb->hash, tb->size, TString *);
	tb->size = newsize;
	tb->hash = newhash;
}

static TString *newlstr(lua_State * L, const char *str, size_t l,
			unsigned int h)
{
	TString *ts;
	stringtable *tb;
	if (l + 1 >
	    (((size_t)(~(size_t)0) - 2) - sizeof(TString)) / sizeof(char))
		luaM_toobig(L);
	ts = cast(TString *,
		  luaM_malloc(L, (l + 1) * sizeof(char) + sizeof(TString)));
	ts->tsv.len = l;
	ts->tsv.hash = h;
	ts->tsv.marked = luaC_white(G(L));
	ts->tsv.tt = 4;
	ts->tsv.reserved = 0;
	memcpy(ts + 1, str, l * sizeof(char));
	((char *)(ts + 1))[l] = '\0';
	tb = &G(L)->strt;
	h = lmod(h, tb->size);
	ts->tsv.next = tb->hash[h];
	tb->hash[h] = obj2gco(ts);
	tb->nuse++;
	if (tb->nuse > cast(lu_int32, tb->size)
	    && tb->size <= (INT_MAX - 2) / 2)
		luaS_resize(L, tb->size * 2);
	return ts;
}

static TString *luaS_newlstr(lua_State * L, const char *str, size_t l)
{
	GCObject *o;
	unsigned int h = cast(unsigned int, l);
	size_t step = (l >> 5) + 1;
	size_t l1;
	for (l1 = l; l1 >= step; l1 -= step)
		h = h ^ ((h << 5) + (h >> 2) +
			 cast(unsigned char, str[l1 - 1]));
	for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; o != NULL;
	     o = o->gch.next) {
		TString *ts = rawgco2ts(o);
		if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
			if (isdead(G(L), o))
				changewhite(o);
			return ts;
		}
	}
	return newlstr(L, str, l, h);
}

static Udata *luaS_newudata(lua_State * L, size_t s, Table * e)
{
	Udata *u;
	if (s > ((size_t)(~(size_t)0) - 2) - sizeof(Udata))
		luaM_toobig(L);
	u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata)));
	u->uv.marked = luaC_white(G(L));
	u->uv.tt = 7;
	u->uv.len = s;
	u->uv.metatable = NULL;
	u->uv.env = e;
	u->uv.next = G(L)->mainthread->next;
	G(L)->mainthread->next = obj2gco(u);
	return u;
}

#define hashpow2(t,n)(gnode(t,lmod((n),sizenode(t))))
#define hashstr(t,str)hashpow2(t,(str)->tsv.hash)
#define hashboolean(t,p)hashpow2(t,p)
#define hashmod(t,n)(gnode(t,((n)%((sizenode(t)-1)|1))))
#define hashpointer(t,p)hashmod(t,IntPoint(p))
static const Node dummynode_ = {
	{{NULL}, 0},
	{{{NULL}, 0, NULL}}
};

static Node *hashnum(const Table * t, lua_Number n)
{
	unsigned int a[cast_int(sizeof(lua_Number) / sizeof(int))];
	int i;
	if (luai_numeq(n, 0))
		return gnode(t, 0);
	memcpy(a, &n, sizeof(a));
	for (i = 1; i < cast_int(sizeof(lua_Number) / sizeof(int)); i++)
		a[0] += a[i];
	return hashmod(t, a[0]);
}

static Node *mainposition(const Table * t, const TValue * key)
{
	switch (ttype(key)) {
	case 3:
		return hashnum(t, nvalue(key));
	case 4:
		return hashstr(t, rawtsvalue(key));
	case 1:
		return hashboolean(t, bvalue(key));
	case 2:
		return hashpointer(t, pvalue(key));
	default:
		return hashpointer(t, gcvalue(key));
	}
}

static int arrayindex(const TValue * key)
{
	if (ttisnumber(key)) {
		lua_Number n = nvalue(key);
		int k;
		lua_number2int(k, n);
		if (luai_numeq(cast_num(k), n))
			return k;
	}
	return -1;
}

static int findindex(lua_State * L, Table * t, StkId key)
{
	int i;
	if (ttisnil(key))
		return -1;
	i = arrayindex(key);
	if (0 < i && i <= t->sizearray)
		return i - 1;
	else {
		Node *n = mainposition(t, key);
		do {
			if (luaO_rawequalObj(key2tval(n), key) ||
			    (ttype(gkey(n)) == (8 + 3) && iscollectable(key) &&
			     gcvalue(gkey(n)) == gcvalue(key))) {
				i = cast_int(n - gnode(t, 0));
				return i + t->sizearray;
			} else
				n = gnext(n);
		} while (n);
		luaG_runerror(L, "invalid key to " LUA_QL("next"));
		return 0;
	}
}

static int luaH_next(lua_State * L, Table * t, StkId key)
{
	int i = findindex(L, t, key);
	for (i++; i < t->sizearray; i++) {
		if (!ttisnil(&t->array[i])) {
			setnvalue(key, cast_num(i + 1));
			setobj(L, key + 1, &t->array[i]);
			return 1;
		}
	}
	for (i -= t->sizearray; i < (int)sizenode(t); i++) {
		if (!ttisnil(gval(gnode(t, i)))) {
			setobj(L, key, key2tval(gnode(t, i)));
			setobj(L, key + 1, gval(gnode(t, i)));
			return 1;
		}
	}
	return 0;
}

static int computesizes(int nums[], int *narray)
{
	int i;
	int twotoi;
	int a = 0;
	int na = 0;
	int n = 0;
	for (i = 0, twotoi = 1; twotoi / 2 < *narray; i++, twotoi *= 2) {
		if (nums[i] > 0) {
			a += nums[i];
			if (a > twotoi / 2) {
				n = twotoi;
				na = a;
			}
		}
		if (a == *narray)
			break;
	}
	*narray = n;
	return na;
}

static int countint(const TValue * key, int *nums)
{
	int k = arrayindex(key);
	if (0 < k && k <= (1 << (32 - 2))) {
		nums[ceillog2(k)]++;
		return 1;
	} else
		return 0;
}

static int numusearray(const Table * t, int *nums)
{
	int lg;
	int ttlg;
	int ause = 0;
	int i = 1;
	for (lg = 0, ttlg = 1; lg <= (32 - 2); lg++, ttlg *= 2) {
		int lc = 0;
		int lim = ttlg;
		if (lim > t->sizearray) {
			lim = t->sizearray;
			if (i > lim)
				break;
		}
		for (; i <= lim; i++) {
			if (!ttisnil(&t->array[i - 1]))
				lc++;
		}
		nums[lg] += lc;
		ause += lc;
	}
	return ause;
}

static int numusehash(const Table * t, int *nums, int *pnasize)
{
	int totaluse = 0;
	int ause = 0;
	int i = sizenode(t);
	while (i--) {
		Node *n = &t->node[i];
		if (!ttisnil(gval(n))) {
			ause += countint(key2tval(n), nums);
			totaluse++;
		}
	}
	*pnasize += ause;
	return totaluse;
}

static void setarrayvector(lua_State * L, Table * t, int size)
{
	int i;
	luaM_reallocvector(L, t->array, t->sizearray, size, TValue);
	for (i = t->sizearray; i < size; i++)
		setnilvalue(&t->array[i]);
	t->sizearray = size;
}

static void setnodevector(lua_State * L, Table * t, int size)
{
	int lsize;
	if (size == 0) {
		t->node = cast(Node *, (&dummynode_));
		lsize = 0;
	} else {
		int i;
		lsize = ceillog2(size);
		if (lsize > (32 - 2))
			luaG_runerror(L, "table overflow");
		size = twoto(lsize);
		t->node = luaM_newvector(L, size, Node);
		for (i = 0; i < size; i++) {
			Node *n = gnode(t, i);
			gnext(n) = NULL;
			setnilvalue(gkey(n));
			setnilvalue(gval(n));
		}
	}
	t->lsizenode = cast_byte(lsize);
	t->lastfree = gnode(t, size);
}

static void resize(lua_State * L, Table * t, int nasize, int nhsize)
{
	int i;
	int oldasize = t->sizearray;
	int oldhsize = t->lsizenode;
	Node *nold = t->node;
	if (nasize > oldasize)
		setarrayvector(L, t, nasize);
	setnodevector(L, t, nhsize);
	if (nasize < oldasize) {
		t->sizearray = nasize;
		for (i = nasize; i < oldasize; i++) {
			if (!ttisnil(&t->array[i]))
				setobj(L, luaH_setnum(L, t, i + 1),
				       &t->array[i]);
		}
		luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
	}
	for (i = twoto(oldhsize) - 1; i >= 0; i--) {
		Node *old = nold + i;
		if (!ttisnil(gval(old)))
			setobj(L, luaH_set(L, t, key2tval(old)), gval(old));
	}
	if (nold != (&dummynode_))
		luaM_freearray(L, nold, twoto(oldhsize), Node);
}

static void luaH_resizearray(lua_State * L, Table * t, int nasize)
{
	int nsize = (t->node == (&dummynode_)) ? 0 : sizenode(t);
	resize(L, t, nasize, nsize);
}

static void rehash(lua_State * L, Table * t, const TValue * ek)
{
	int nasize, na;
	int nums[(32 - 2) + 1];
	int i;
	int totaluse;
	for (i = 0; i <= (32 - 2); i++)
		nums[i] = 0;
	nasize = numusearray(t, nums);
	totaluse = nasize;
	totaluse += numusehash(t, nums, &nasize);
	nasize += countint(ek, nums);
	totaluse++;
	na = computesizes(nums, &nasize);
	resize(L, t, nasize, totaluse - na);
}

static Table *luaH_new(lua_State * L, int narray, int nhash)
{
	Table *t = luaM_new(L, Table);
	luaC_link(L, obj2gco(t), 5);
	t->metatable = NULL;
	t->flags = cast_byte(~0);
	t->array = NULL;
	t->sizearray = 0;
	t->lsizenode = 0;
	t->node = cast(Node *, (&dummynode_));
	setarrayvector(L, t, narray);
	setnodevector(L, t, nhash);
	return t;
}

static void luaH_free(lua_State * L, Table * t)
{
	if (t->node != (&dummynode_))
		luaM_freearray(L, t->node, sizenode(t), Node);
	luaM_freearray(L, t->array, t->sizearray, TValue);
	luaM_free(L, t);
}

static Node *getfreepos(Table * t)
{
	while (t->lastfree-- > t->node) {
		if (ttisnil(gkey(t->lastfree)))
			return t->lastfree;
	}
	return NULL;
}

static TValue *newkey(lua_State * L, Table * t, const TValue * key)
{
	Node *mp = mainposition(t, key);
	if (!ttisnil(gval(mp)) || mp == (&dummynode_)) {
		Node *othern;
		Node *n = getfreepos(t);
		if (n == NULL) {
			rehash(L, t, key);
			return luaH_set(L, t, key);
		}
		othern = mainposition(t, key2tval(mp));
		if (othern != mp) {
			while (gnext(othern) != mp)
				othern = gnext(othern);
			gnext(othern) = n;
			*n = *mp;
			gnext(mp) = NULL;
			setnilvalue(gval(mp));
		} else {
			gnext(n) = gnext(mp);
			gnext(mp) = n;
			mp = n;
		}
	}
	gkey(mp)->value = key->value;
	gkey(mp)->tt = key->tt;
	luaC_barriert(L, t, key);
	return gval(mp);
}

static const TValue *luaH_getnum(Table * t, int key)
{
	if (cast(unsigned int, key) - 1 < cast(unsigned int, t->sizearray))
		 return &t->array[key - 1];
	else {
		lua_Number nk = cast_num(key);
		Node *n = hashnum(t, nk);
		do {
			if (ttisnumber(gkey(n))
			    && luai_numeq(nvalue(gkey(n)), nk))
				return gval(n);
			else
				n = gnext(n);
		} while (n);
		return (&luaO_nilobject_);
	}
}

static const TValue *luaH_getstr(Table * t, TString * key)
{
	Node *n = hashstr(t, key);
	do {
		if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)
			return gval(n);
		else
			n = gnext(n);
	} while (n);
	return (&luaO_nilobject_);
}

static const TValue *luaH_get(Table * t, const TValue * key)
{
	switch (ttype(key)) {
	case 0:
		return (&luaO_nilobject_);
	case 4:
		return luaH_getstr(t, rawtsvalue(key));
	case 3:{
			int k;
			lua_Number n = nvalue(key);
			lua_number2int(k, n);
			if (luai_numeq(cast_num(k), nvalue(key)))
				return luaH_getnum(t, k);
		}
	default:{
			Node *n = mainposition(t, key);
			do {
				if (luaO_rawequalObj(key2tval(n), key))
					return gval(n);
				else
					n = gnext(n);
			} while (n);
			return (&luaO_nilobject_);
		}
	}
}

static TValue *luaH_set(lua_State * L, Table * t, const TValue * key)
{
	const TValue *p = luaH_get(t, key);
	t->flags = 0;
	if (p != (&luaO_nilobject_))
		return cast(TValue *, p);
	else {
		if (ttisnil(key))
			luaG_runerror(L, "table index is nil");
		else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
			luaG_runerror(L, "table index is NaN");
		return newkey(L, t, key);
	}
}

static TValue *luaH_setnum(lua_State * L, Table * t, int key)
{
	const TValue *p = luaH_getnum(t, key);
	if (p != (&luaO_nilobject_))
		return cast(TValue *, p);
	else {
		TValue k;
		setnvalue(&k, cast_num(key));
		return newkey(L, t, &k);
	}
}

static TValue *luaH_setstr(lua_State * L, Table * t, TString * key)
{
	const TValue *p = luaH_getstr(t, key);
	if (p != (&luaO_nilobject_))
		return cast(TValue *, p);
	else {
		TValue k;
		setsvalue(L, &k, key);
		return newkey(L, t, &k);
	}
}

static int unbound_search(Table * t, unsigned int j)
{
	unsigned int i = j;
	j++;
	while (!ttisnil(luaH_getnum(t, j))) {
		i = j;
		j *= 2;
		if (j > cast(unsigned int, (INT_MAX - 2))) {
			i = 1;
			while (!ttisnil(luaH_getnum(t, i)))
				i++;
			return i - 1;
		}
	}
	while (j - i > 1) {
		unsigned int m = (i + j) / 2;
		if (ttisnil(luaH_getnum(t, m)))
			j = m;
		else
			i = m;
	}
	return i;
}

static int luaH_getn(Table * t)
{
	unsigned int j = t->sizearray;
	if (j > 0 && ttisnil(&t->array[j - 1])) {
		unsigned int i = 0;
		while (j - i > 1) {
			unsigned int m = (i + j) / 2;
			if (ttisnil(&t->array[m - 1]))
				j = m;
			else
				i = m;
		}
		return i;
	} else if (t->node == (&dummynode_))
		return j;
	else
		return unbound_search(t, j);
}

#define makewhite(g,x)((x)->gch.marked=cast_byte(((x)->gch.marked&cast_byte(~(bitmask(2)|bit2mask(0,1))))|luaC_white(g)))
#define white2gray(x)reset2bits((x)->gch.marked,0,1)
#define black2gray(x)resetbit((x)->gch.marked,2)
#define stringmark(s)reset2bits((s)->tsv.marked,0,1)
#define isfinalized(u)testbit((u)->marked,3)
#define markfinalized(u)l_setbit((u)->marked,3)
#define markvalue(g,o){checkconsistency(o);if(iscollectable(o)&&iswhite(gcvalue(o)))reallymarkobject(g,gcvalue(o));}
#define markobject(g,t){if(iswhite(obj2gco(t)))reallymarkobject(g,obj2gco(t));}
#define setthreshold(g)(g->GCthreshold=(g->estimate/100)*g->gcpause)
static void removeentry(Node * n)
{
	if (iscollectable(gkey(n)))
		setttype(gkey(n), (8 + 3));
}

static void reallymarkobject(global_State * g, GCObject * o)
{
	white2gray(o);
	switch (o->gch.tt) {
	case 4:{
			return;
		}
	case 7:{
			Table *mt = gco2u(o)->metatable;
			gray2black(o);
			if (mt)
				markobject(g, mt);
			markobject(g, gco2u(o)->env);
			return;
		}
	case (8 + 2):{
			UpVal *uv = gco2uv(o);
			markvalue(g, uv->v);
			if (uv->v == &uv->u.value)
				gray2black(o);
			return;
		}
	case 6:{
			gco2cl(o)->c.gclist = g->gray;
			g->gray = o;
			break;
		}
	case 5:{
			gco2h(o)->gclist = g->gray;
			g->gray = o;
			break;
		}
	case 8:{
			gco2th(o)->gclist = g->gray;
			g->gray = o;
			break;
		}
	case (8 + 1):{
			gco2p(o)->gclist = g->gray;
			g->gray = o;
			break;
		}
	default:;
	}
}

static void marktmu(global_State * g)
{
	GCObject *u = g->tmudata;
	if (u) {
		do {
			u = u->gch.next;
			makewhite(g, u);
			reallymarkobject(g, u);
		} while (u != g->tmudata);
	}
}

static size_t luaC_separateudata(lua_State * L, int all)
{
	global_State *g = G(L);
	size_t deadmem = 0;
	GCObject **p = &g->mainthread->next;
	GCObject *curr;
	while ((curr = *p) != NULL) {
		if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
			p = &curr->gch.next;
		else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
			markfinalized(gco2u(curr));
			p = &curr->gch.next;
		} else {
			deadmem += sizeudata(gco2u(curr));
			markfinalized(gco2u(curr));
			*p = curr->gch.next;
			if (g->tmudata == NULL)
				g->tmudata = curr->gch.next = curr;
			else {
				curr->gch.next = g->tmudata->gch.next;
				g->tmudata->gch.next = curr;
				g->tmudata = curr;
			}
		}
	}
	return deadmem;
}

static int traversetable(global_State * g, Table * h)
{
	int i;
	int weakkey = 0;
	int weakvalue = 0;
	const TValue *mode;
	if (h->metatable)
		markobject(g, h->metatable);
	mode = gfasttm(g, h->metatable, TM_MODE);
	if (mode && ttisstring(mode)) {
		weakkey = (strchr(svalue(mode), 'k') != NULL);
		weakvalue = (strchr(svalue(mode), 'v') != NULL);
		if (weakkey || weakvalue) {
			h->marked &= ~(bitmask(3) | bitmask(4));
			h->marked |= cast_byte((weakkey << 3) |
					       (weakvalue << 4));
			h->gclist = g->weak;
			g->weak = obj2gco(h);
		}
	}
	if (weakkey && weakvalue)
		return 1;
	if (!weakvalue) {
		i = h->sizearray;
		while (i--)
			markvalue(g, &h->array[i]);
	}
	i = sizenode(h);
	while (i--) {
		Node *n = gnode(h, i);
		if (ttisnil(gval(n)))
			removeentry(n);
		else {
			if (!weakkey)
				markvalue(g, gkey(n));
			if (!weakvalue)
				markvalue(g, gval(n));
		}
	}
	return weakkey || weakvalue;
}

static void traverseproto(global_State * g, Proto * f)
{
	int i;
	if (f->source)
		stringmark(f->source);
	for (i = 0; i < f->sizek; i++)
		markvalue(g, &f->k[i]);
	for (i = 0; i < f->sizeupvalues; i++) {
		if (f->upvalues[i])
			stringmark(f->upvalues[i]);
	}
	for (i = 0; i < f->sizep; i++) {
		if (f->p[i])
			markobject(g, f->p[i]);
	}
	for (i = 0; i < f->sizelocvars; i++) {
		if (f->locvars[i].varname)
			stringmark(f->locvars[i].varname);
	}
}

static void traverseclosure(global_State * g, Closure * cl)
{
	markobject(g, cl->c.env);
	if (cl->c.isC) {
		int i;
		for (i = 0; i < cl->c.nupvalues; i++)
			markvalue(g, &cl->c.upvalue[i]);
	} else {
		int i;
		markobject(g, cl->l.p);
		for (i = 0; i < cl->l.nupvalues; i++)
			markobject(g, cl->l.upvals[i]);
	}
}

static void checkstacksizes(lua_State * L, StkId max)
{
	int ci_used = cast_int(L->ci - L->base_ci);
	int s_used = cast_int(max - L->stack);
	if (L->size_ci > 20000)
		return;
	if (4 * ci_used < L->size_ci && 2 * 8 < L->size_ci)
		luaD_reallocCI(L, L->size_ci / 2);
	condhardstacktests(luaD_reallocCI(L, ci_used + 1));
	if (4 * s_used < L->stacksize && 2 * ((2 * 20) + 5) < L->stacksize)
		luaD_reallocstack(L, L->stacksize / 2);
	condhardstacktests(luaD_reallocstack(L, s_used));
}

static void traversestack(global_State * g, lua_State * l)
{
	StkId o, lim;
	CallInfo *ci;
	markvalue(g, gt(l));
	lim = l->top;
	for (ci = l->base_ci; ci <= l->ci; ci++) {
		if (lim < ci->top)
			lim = ci->top;
	}
	for (o = l->stack; o < l->top; o++)
		markvalue(g, o);
	for (; o <= lim; o++)
		setnilvalue(o);
	checkstacksizes(l, lim);
}

static l_mem propagatemark(global_State * g)
{
	GCObject *o = g->gray;
	gray2black(o);
	switch (o->gch.tt) {
	case 5:{
			Table *h = gco2h(o);
			g->gray = h->gclist;
			if (traversetable(g, h))
				black2gray(o);
			return sizeof(Table) + sizeof(TValue) * h->sizearray +
			    sizeof(Node) * sizenode(h);
		}
	case 6:{
			Closure *cl = gco2cl(o);
			g->gray = cl->c.gclist;
			traverseclosure(g, cl);
			return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
			    sizeLclosure(cl->l.nupvalues);
		}
	case 8:{
			lua_State *th = gco2th(o);
			g->gray = th->gclist;
			th->gclist = g->grayagain;
			g->grayagain = o;
			black2gray(o);
			traversestack(g, th);
			return sizeof(lua_State) +
			    sizeof(TValue) * th->stacksize +
			    sizeof(CallInfo) * th->size_ci;
		}
	case (8 + 1):{
			Proto *p = gco2p(o);
			g->gray = p->gclist;
			traverseproto(g, p);
			return sizeof(Proto) +
			    sizeof(Instruction) * p->sizecode +
			    sizeof(Proto *) * p->sizep +
			    sizeof(TValue) * p->sizek +
			    sizeof(int) * p->sizelineinfo +
			    sizeof(LocVar) * p->sizelocvars +
			    sizeof(TString *) * p->sizeupvalues;
		}
	default:
		return 0;
	}
}

static size_t propagateall(global_State * g)
{
	size_t m = 0;
	while (g->gray)
		m += propagatemark(g);
	return m;
}

static int iscleared(const TValue * o, int iskey)
{
	if (!iscollectable(o))
		return 0;
	if (ttisstring(o)) {
		stringmark(rawtsvalue(o));
		return 0;
	}
	return iswhite(gcvalue(o)) ||
	    (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));
}

static void cleartable(GCObject * l)
{
	while (l) {
		Table *h = gco2h(l);
		int i = h->sizearray;
		if (testbit(h->marked, 4)) {
			while (i--) {
				TValue *o = &h->array[i];
				if (iscleared(o, 0))
					setnilvalue(o);
			}
		}
		i = sizenode(h);
		while (i--) {
			Node *n = gnode(h, i);
			if (!ttisnil(gval(n)) &&
			    (iscleared(key2tval(n), 1)
			     || iscleared(gval(n), 0))) {
				setnilvalue(gval(n));
				removeentry(n);
			}
		}
		l = h->gclist;
	}
}

static void freeobj(lua_State * L, GCObject * o)
{
	switch (o->gch.tt) {
	case (8 + 1):
		luaF_freeproto(L, gco2p(o));
		break;
	case 6:
		luaF_freeclosure(L, gco2cl(o));
		break;
	case (8 + 2):
		luaF_freeupval(L, gco2uv(o));
		break;
	case 5:
		luaH_free(L, gco2h(o));
		break;
	case 8:{
			luaE_freethread(L, gco2th(o));
			break;
		}
	case 4:{
			G(L)->strt.nuse--;
			luaM_freemem(L, o, sizestring(gco2ts(o)));
			break;
		}
	case 7:{
			luaM_freemem(L, o, sizeudata(gco2u(o)));
			break;
		}
	default:;
	}
}

#define sweepwholelist(L,p)sweeplist(L,p,((lu_mem)(~(lu_mem)0)-2))
static GCObject **sweeplist(lua_State * L, GCObject ** p, lu_mem count)
{
	GCObject *curr;
	global_State *g = G(L);
	int deadmask = otherwhite(g);
	while ((curr = *p) != NULL && count-- > 0) {
		if (curr->gch.tt == 8)
			sweepwholelist(L, &gco2th(curr)->openupval);
		if ((curr->gch.marked ^ bit2mask(0, 1)) & deadmask) {
			makewhite(g, curr);
			p = &curr->gch.next;
		} else {
			*p = curr->gch.next;
			if (curr == g->rootgc)
				g->rootgc = curr->gch.next;
			freeobj(L, curr);
		}
	}
	return p;
}

static void checkSizes(lua_State * L)
{
	global_State *g = G(L);
	if (g->strt.nuse < cast(lu_int32, g->strt.size / 4) &&
	    g->strt.size > 32 * 2)
		luaS_resize(L, g->strt.size / 2);
	if (luaZ_sizebuffer(&g->buff) > 32 * 2) {
		size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
		luaZ_resizebuffer(L, &g->buff, newsize);
	}
}

static void GCTM(lua_State * L)
{
	global_State *g = G(L);
	GCObject *o = g->tmudata->gch.next;
	Udata *udata = rawgco2u(o);
	const TValue *tm;
	if (o == g->tmudata)
		g->tmudata = NULL;
	else
		g->tmudata->gch.next = udata->uv.next;
	udata->uv.next = g->mainthread->next;
	g->mainthread->next = o;
	makewhite(g, o);
	tm = fasttm(L, udata->uv.metatable, TM_GC);
	if (tm != NULL) {
		lu_byte oldah = L->allowhook;
		lu_mem oldt = g->GCthreshold;
		L->allowhook = 0;
		g->GCthreshold = 2 * g->totalbytes;
		setobj(L, L->top, tm);
		setuvalue(L, L->top + 1, udata);
		L->top += 2;
		luaD_call(L, L->top - 2, 0);
		L->allowhook = oldah;
		g->GCthreshold = oldt;
	}
}

static void luaC_callGCTM(lua_State * L)
{
	while (G(L)->tmudata)
		GCTM(L);
}

static void luaC_freeall(lua_State * L)
{
	global_State *g = G(L);
	int i;
	g->currentwhite = bit2mask(0, 1) | bitmask(6);
	sweepwholelist(L, &g->rootgc);
	for (i = 0; i < g->strt.size; i++)
		sweepwholelist(L, &g->strt.hash[i]);
}

static void markmt(global_State * g)
{
	int i;
	for (i = 0; i < (8 + 1); i++)
		if (g->mt[i])
			markobject(g, g->mt[i]);
}

static void markroot(lua_State * L)
{
	global_State *g = G(L);
	g->gray = NULL;
	g->grayagain = NULL;
	g->weak = NULL;
	markobject(g, g->mainthread);
	markvalue(g, gt(g->mainthread));
	markvalue(g, registry(L));
	markmt(g);
	g->gcstate = 1;
}

static void remarkupvals(global_State * g)
{
	UpVal *uv;
	for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
		if (isgray(obj2gco(uv)))
			markvalue(g, uv->v);
	}
}

static void atomic(lua_State * L)
{
	global_State *g = G(L);
	size_t udsize;
	remarkupvals(g);
	propagateall(g);
	g->gray = g->weak;
	g->weak = NULL;
	markobject(g, L);
	markmt(g);
	propagateall(g);
	g->gray = g->grayagain;
	g->grayagain = NULL;
	propagateall(g);
	udsize = luaC_separateudata(L, 0);
	marktmu(g);
	udsize += propagateall(g);
	cleartable(g->weak);
	g->currentwhite = cast_byte(otherwhite(g));
	g->sweepstrgc = 0;
	g->sweepgc = &g->rootgc;
	g->gcstate = 2;
	g->estimate = g->totalbytes - udsize;
}

static l_mem singlestep(lua_State * L)
{
	global_State *g = G(L);
	switch (g->gcstate) {
	case 0:{
			markroot(L);
			return 0;
		}
	case 1:{
			if (g->gray)
				return propagatemark(g);
			else {
				atomic(L);
				return 0;
			}
		}
	case 2:{
			lu_mem old = g->totalbytes;
			sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
			if (g->sweepstrgc >= g->strt.size)
				g->gcstate = 3;
			g->estimate -= old - g->totalbytes;
			return 10;
		}
	case 3:{
			lu_mem old = g->totalbytes;
			g->sweepgc = sweeplist(L, g->sweepgc, 40);
			if (*g->sweepgc == NULL) {
				checkSizes(L);
				g->gcstate = 4;
			}
			g->estimate -= old - g->totalbytes;
			return 40 * 10;
		}
	case 4:{
			if (g->tmudata) {
				GCTM(L);
				if (g->estimate > 100)
					g->estimate -= 100;
				return 100;
			} else {
				g->gcstate = 0;
				g->gcdept = 0;
				return 0;
			}
		}
	default:
		return 0;
	}
}

static void luaC_step(lua_State * L)
{
	global_State *g = G(L);
	l_mem lim = (1024u / 100) * g->gcstepmul;
	if (lim == 0)
		lim = (((lu_mem) (~(lu_mem) 0) - 2) - 1) / 2;
	g->gcdept += g->totalbytes - g->GCthreshold;
	do {
		lim -= singlestep(L);
		if (g->gcstate == 0)
			break;
	} while (lim > 0);
	if (g->gcstate != 0) {
		if (g->gcdept < 1024u)
			g->GCthreshold = g->totalbytes + 1024u;
		else {
			g->gcdept -= 1024u;
			g->GCthreshold = g->totalbytes;
		}
	} else {
		setthreshold(g);
	}
}

static void luaC_barrierf(lua_State * L, GCObject * o, GCObject * v)
{
	global_State *g = G(L);
	if (g->gcstate == 1)
		reallymarkobject(g, v);
	else
		makewhite(g, o);
}

static void luaC_barrierback(lua_State * L, Table * t)
{
	global_State *g = G(L);
	GCObject *o = obj2gco(t);
	black2gray(o);
	t->gclist = g->grayagain;
	g->grayagain = o;
}

static void luaC_link(lua_State * L, GCObject * o, lu_byte tt)
{
	global_State *g = G(L);
	o->gch.next = g->rootgc;
	g->rootgc = o;
	o->gch.marked = luaC_white(g);
	o->gch.tt = tt;
}

static void luaC_linkupval(lua_State * L, UpVal * uv)
{
	global_State *g = G(L);
	GCObject *o = obj2gco(uv);
	o->gch.next = g->rootgc;
	g->rootgc = o;
	if (isgray(o)) {
		if (g->gcstate == 1) {
			gray2black(o);
			luaC_barrier(L, uv, uv->v);
		} else {
			makewhite(g, o);
		}
	}
}

typedef union {
	lua_Number r;
	TString *ts;
} SemInfo;
typedef struct Token {
	int token;
	SemInfo seminfo;
} Token;
typedef struct LexState {
	int current;
	int linenumber;
	int lastline;
	Token t;
	Token lookahead;
	struct FuncState *fs;
	struct lua_State *L;
	ZIO *z;
	Mbuffer *buff;
	TString *source;
	char decpoint;
} LexState;
static void luaX_init(lua_State * L);
static void luaX_lexerror(LexState * ls, const char *msg, int token);
#define state_size(x)(sizeof(x)+0)
#define fromstate(l)(cast(lu_byte*,(l))-0)
#define tostate(l)(cast(lua_State*,cast(lu_byte*,l)+0))
typedef struct LG {
	lua_State l;
	global_State g;
} LG;
static void stack_init(lua_State * L1, lua_State * L)
{
	L1->base_ci = luaM_newvector(L, 8, CallInfo);
	L1->ci = L1->base_ci;
	L1->size_ci = 8;
	L1->end_ci = L1->base_ci + L1->size_ci - 1;
	L1->stack = luaM_newvector(L, (2 * 20) + 5, TValue);
	L1->stacksize = (2 * 20) + 5;
	L1->top = L1->stack;
	L1->stack_last = L1->stack + (L1->stacksize - 5) - 1;
	L1->ci->func = L1->top;
	setnilvalue(L1->top++);
	L1->base = L1->ci->base = L1->top;
	L1->ci->top = L1->top + 20;
}

static void freestack(lua_State * L, lua_State * L1)
{
	luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);
	luaM_freearray(L, L1->stack, L1->stacksize, TValue);
}

static void f_luaopen(lua_State * L, void *ud)
{
	global_State *g = G(L);
	UNUSED(ud);
	stack_init(L, L);
	sethvalue(L, gt(L), luaH_new(L, 0, 2));
	sethvalue(L, registry(L), luaH_new(L, 0, 2));
	luaS_resize(L, 32);
	luaT_init(L);
	luaX_init(L);
	luaS_fix(luaS_newliteral(L, "not enough memory"));
	g->GCthreshold = 4 * g->totalbytes;
}

static void preinit_state(lua_State * L, global_State * g)
{
	G(L) = g;
	L->stack = NULL;
	L->stacksize = 0;
	L->errorJmp = NULL;
	L->hook = NULL;
	L->hookmask = 0;
	L->basehookcount = 0;
	L->allowhook = 1;
	resethookcount(L);
	L->openupval = NULL;
	L->size_ci = 0;
	L->nCcalls = L->baseCcalls = 0;
	L->status = 0;
	L->base_ci = L->ci = NULL;
	L->savedpc = NULL;
	L->errfunc = 0;
	setnilvalue(gt(L));
}

static void close_state(lua_State * L)
{
	global_State *g = G(L);
	luaF_close(L, L->stack);
	luaC_freeall(L);
	luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
	luaZ_freebuffer(L, &g->buff);
	freestack(L, L);
	(*g->frealloc) (g->ud, fromstate(L), state_size(LG), 0);
}

static void luaE_freethread(lua_State * L, lua_State * L1)
{
	luaF_close(L1, L1->stack);
	freestack(L, L1);
	luaM_freemem(L, fromstate(L1), state_size(lua_State));
}

static lua_State *lua_newstate(lua_Alloc f, void *ud)
{
	int i;
	lua_State *L;
	global_State *g;
	void *l = (*f) (ud, NULL, 0, state_size(LG));
	if (l == NULL)
		return NULL;
	L = tostate(l);
	g = &((LG *) L)->g;
	L->next = NULL;
	L->tt = 8;
	g->currentwhite = bit2mask(0, 5);
	L->marked = luaC_white(g);
	set2bits(L->marked, 5, 6);
	preinit_state(L, g);
	g->frealloc = f;
	g->ud = ud;
	g->mainthread = L;
	g->uvhead.u.l.prev = &g->uvhead;
	g->uvhead.u.l.next = &g->uvhead;
	g->GCthreshold = 0;
	g->strt.size = 0;
	g->strt.nuse = 0;
	g->strt.hash = NULL;
	setnilvalue(registry(L));
	luaZ_initbuffer(L, &g->buff);
	g->panic = NULL;
	g->gcstate = 0;
	g->rootgc = obj2gco(L);
	g->sweepstrgc = 0;
	g->sweepgc = &g->rootgc;
	g->gray = NULL;
	g->grayagain = NULL;
	g->weak = NULL;
	g->tmudata = NULL;
	g->totalbytes = sizeof(LG);
	g->gcpause = 200;
	g->gcstepmul = 200;
	g->gcdept = 0;
	for (i = 0; i < (8 + 1); i++)
		g->mt[i] = NULL;
	if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
		close_state(L);
		L = NULL;
	} else {
	}
	return L;
}

static void callallgcTM(lua_State * L, void *ud)
{
	UNUSED(ud);
	luaC_callGCTM(L);
}

static void lua_close(lua_State * L)
{
	L = G(L)->mainthread;
	luaF_close(L, L->stack);
	luaC_separateudata(L, 1);
	L->errfunc = 0;
	do {
		L->ci = L->base_ci;
		L->base = L->top = L->ci->base;
		L->nCcalls = L->baseCcalls = 0;
	} while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
	close_state(L);
}

#define getcode(fs,e)((fs)->f->code[(e)->u.s.info])
#define luaK_codeAsBx(fs,o,A,sBx)luaK_codeABx(fs,o,A,(sBx)+(((1<<(9+9))-1)>>1))
#define luaK_setmultret(fs,e)luaK_setreturns(fs,e,(-1))
static int luaK_codeABx(FuncState * fs, OpCode o, int A, unsigned int Bx);
static int luaK_codeABC(FuncState * fs, OpCode o, int A, int B, int C);
static void luaK_setreturns(FuncState * fs, expdesc * e, int nresults);
static void luaK_patchtohere(FuncState * fs, int list);
static void luaK_concat(FuncState * fs, int *l1, int l2);
static int currentpc(lua_State * L, CallInfo * ci)
{
	if (!isLua(ci))
		return -1;
	if (ci == L->ci)
		ci->savedpc = L->savedpc;
	return pcRel(ci->savedpc, ci_func(ci)->l.p);
}

static int currentline(lua_State * L, CallInfo * ci)
{
	int pc = currentpc(L, ci);
	if (pc < 0)
		return -1;
	else
		return getline_(ci_func(ci)->l.p, pc);
}

static int lua_getstack(lua_State * L, int level, lua_Debug * ar)
{
	int status;
	CallInfo *ci;
	for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
		level--;
		if (f_isLua(ci))
			level -= ci->tailcalls;
	}
	if (level == 0 && ci > L->base_ci) {
		status = 1;
		ar->i_ci = cast_int(ci - L->base_ci);
	} else if (level < 0) {
		status = 1;
		ar->i_ci = 0;
	} else
		status = 0;
	return status;
}

static Proto *getluaproto(CallInfo * ci)
{
	return (isLua(ci) ? ci_func(ci)->l.p : NULL);
}

static void funcinfo(lua_Debug * ar, Closure * cl)
{
	if (cl->c.isC) {
		ar->source = "=[C]";
		ar->linedefined = -1;
		ar->lastlinedefined = -1;
		ar->what = "C";
	} else {
		ar->source = getstr(cl->l.p->source);
		ar->linedefined = cl->l.p->linedefined;
		ar->lastlinedefined = cl->l.p->lastlinedefined;
		ar->what = (ar->linedefined == 0) ? "main" : "Lua";
	}
	luaO_chunkid(ar->short_src, ar->source, 60);
}

static void info_tailcall(lua_Debug * ar)
{
	ar->name = ar->namewhat = "";
	ar->what = "tail";
	ar->lastlinedefined = ar->linedefined = ar->currentline = -1;
	ar->source = "=(tail call)";
	luaO_chunkid(ar->short_src, ar->source, 60);
	ar->nups = 0;
}

static void collectvalidlines(lua_State * L, Closure * f)
{
	if (f == NULL || f->c.isC) {
		setnilvalue(L->top);
	} else {
		Table *t = luaH_new(L, 0, 0);
		int *lineinfo = f->l.p->lineinfo;
		int i;
		for (i = 0; i < f->l.p->sizelineinfo; i++)
			setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
		sethvalue(L, L->top, t);
	}
	incr_top(L);
}

static int auxgetinfo(lua_State * L, const char *what, lua_Debug * ar,
		      Closure * f, CallInfo * ci)
{
	int status = 1;
	if (f == NULL) {
		info_tailcall(ar);
		return status;
	}
	for (; *what; what++) {
		switch (*what) {
		case 'S':{
				funcinfo(ar, f);
				break;
			}
		case 'l':{
				ar->currentline =
				    (ci) ? currentline(L, ci) : -1;
				break;
			}
		case 'u':{
				ar->nups = f->c.nupvalues;
				break;
			}
		case 'n':{
				ar->namewhat = (ci) ? NULL : NULL;
				if (ar->namewhat == NULL) {
					ar->namewhat = "";
					ar->name = NULL;
				}
				break;
			}
		case 'L':
		case 'f':
			break;
		default:
			status = 0;
		}
	}
	return status;
}

static int lua_getinfo(lua_State * L, const char *what, lua_Debug * ar)
{
	int status;
	Closure *f = NULL;
	CallInfo *ci = NULL;
	if (*what == '>') {
		StkId func = L->top - 1;
		luai_apicheck(L, ttisfunction(func));
		what++;
		f = clvalue(func);
		L->top--;
	} else if (ar->i_ci != 0) {
		ci = L->base_ci + ar->i_ci;
		f = clvalue(ci->func);
	}
	status = auxgetinfo(L, what, ar, f, ci);
	if (strchr(what, 'f')) {
		if (f == NULL)
			setnilvalue(L->top);
		else
			setclvalue(L, L->top, f);
		incr_top(L);
	}
	if (strchr(what, 'L'))
		collectvalidlines(L, f);
	return status;
}

static int isinstack(CallInfo * ci, const TValue * o)
{
	StkId p;
	for (p = ci->base; p < ci->top; p++)
		if (o == p)
			return 1;
	return 0;
}

static void luaG_typeerror(lua_State * L, const TValue * o, const char *op)
{
	const char *name = NULL;
	const char *t = luaT_typenames[ttype(o)];
	const char *kind = (isinstack(L->ci, o)) ? NULL : NULL;
	if (kind)
		luaG_runerror(L,
			      "attempt to %s %s " LUA_QL("%s") " (a %s value)",
			      op, kind, name, t);
	else
		luaG_runerror(L, "attempt to %s a %s value", op, t);
}

static void luaG_concaterror(lua_State * L, StkId p1, StkId p2)
{
	if (ttisstring(p1) || ttisnumber(p1))
		p1 = p2;
	luaG_typeerror(L, p1, "concatenate");
}

static void luaG_aritherror(lua_State * L, const TValue * p1, const TValue * p2)
{
	TValue temp;
	if (luaV_tonumber(p1, &temp) == NULL)
		p2 = p1;
	luaG_typeerror(L, p2, "perform arithmetic on");
}

static int luaG_ordererror(lua_State * L, const TValue * p1, const TValue * p2)
{
	const char *t1 = luaT_typenames[ttype(p1)];
	const char *t2 = luaT_typenames[ttype(p2)];
	if (t1[2] == t2[2])
		luaG_runerror(L, "attempt to compare two %s values", t1);
	else
		luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
	return 0;
}

static void addinfo(lua_State * L, const char *msg)
{
	CallInfo *ci = L->ci;
	if (isLua(ci)) {
		char buff[60];
		int line = currentline(L, ci);
		luaO_chunkid(buff, getstr(getluaproto(ci)->source), 60);
		luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
	}
}

static void luaG_errormsg(lua_State * L)
{
	if (L->errfunc != 0) {
		StkId errfunc = restorestack(L, L->errfunc);
		if (!ttisfunction(errfunc))
			luaD_throw(L, 5);
		setobj(L, L->top, L->top - 1);
		setobj(L, L->top - 1, errfunc);
		incr_top(L);
		luaD_call(L, L->top - 2, 1);
	}
	luaD_throw(L, 2);
}

static void luaG_runerror(lua_State * L, const char *fmt, ...)
{
	va_list argp;
	va_start(argp, fmt);
	addinfo(L, luaO_pushvfstring(L, fmt, argp));
	va_end(argp);
	luaG_errormsg(L);
}

static int luaZ_fill(ZIO * z)
{
	size_t size;
	lua_State *L = z->L;
	const char *buff;
	buff = z->reader(L, z->data, &size);
	if (buff == NULL || size == 0)
		return (-1);
	z->n = size - 1;
	z->p = buff;
	return char2int(*(z->p++));
}

static void luaZ_init(lua_State * L, ZIO * z, lua_Reader reader, void *data)
{
	z->L = L;
	z->reader = reader;
	z->data = data;
	z->n = 0;
	z->p = NULL;
}

static char *luaZ_openspace(lua_State * L, Mbuffer * buff, size_t n)
{
	if (n > buff->buffsize) {
		if (n < 32)
			n = 32;
		luaZ_resizebuffer(L, buff, n);
	}
	return buff->buffer;
}

#define opmode(t,a,b,c,m)(((t)<<7)|((a)<<6)|((b)<<4)|((c)<<2)|(m))
static const lu_byte luaP_opmodes[(cast(int, OP_VARARG) + 1)] = {
	opmode(0, 1, OpArgR, OpArgN, iABC)
	    , opmode(0, 1, OpArgK, OpArgN, iABx)
	    , opmode(0, 1, OpArgU, OpArgU, iABC)
	    , opmode(0, 1, OpArgR, OpArgN, iABC)
	    , opmode(0, 1, OpArgU, OpArgN, iABC)
	    , opmode(0, 1, OpArgK, OpArgN, iABx)
	    , opmode(0, 1, OpArgR, OpArgK, iABC)
	    , opmode(0, 0, OpArgK, OpArgN, iABx)
	    , opmode(0, 0, OpArgU, OpArgN, iABC)
	    , opmode(0, 0, OpArgK, OpArgK, iABC)
	    , opmode(0, 1, OpArgU, OpArgU, iABC)
	    , opmode(0, 1, OpArgR, OpArgK, iABC)
	    , opmode(0, 1, OpArgK, OpArgK, iABC)
	    , opmode(0, 1, OpArgK, OpArgK, iABC)
	    , opmode(0, 1, OpArgK, OpArgK, iABC)
	    , opmode(0, 1, OpArgK, OpArgK, iABC)
	    , opmode(0, 1, OpArgK, OpArgK, iABC)
	    , opmode(0, 1, OpArgK, OpArgK, iABC)
	    , opmode(0, 1, OpArgR, OpArgN, iABC)
	    , opmode(0, 1, OpArgR, OpArgN, iABC)
	    , opmode(0, 1, OpArgR, OpArgN, iABC)
	    , opmode(0, 1, OpArgR, OpArgR, iABC)
	    , opmode(0, 0, OpArgR, OpArgN, iAsBx)
	    , opmode(1, 0, OpArgK, OpArgK, iABC)
	    , opmode(1, 0, OpArgK, OpArgK, iABC)
	    , opmode(1, 0, OpArgK, OpArgK, iABC)
	    , opmode(1, 1, OpArgR, OpArgU, iABC)
	    , opmode(1, 1, OpArgR, OpArgU, iABC)
	    , opmode(0, 1, OpArgU, OpArgU, iABC)
	    , opmode(0, 1, OpArgU, OpArgU, iABC)
	    , opmode(0, 0, OpArgU, OpArgN, iABC)
	    , opmode(0, 1, OpArgR, OpArgN, iAsBx)
	    , opmode(0, 1, OpArgR, OpArgN, iAsBx)
	    , opmode(1, 0, OpArgN, OpArgU, iABC)
	    , opmode(0, 0, OpArgU, OpArgU, iABC)
	    , opmode(0, 0, OpArgN, OpArgN, iABC)
	    , opmode(0, 1, OpArgU, OpArgN, iABx)
	    , opmode(0, 1, OpArgU, OpArgN, iABC)
};

#define next(ls)(ls->current=zgetc(ls->z))
#define currIsNewline(ls)(ls->current=='\n'||ls->current=='\r')
static const char *const luaX_tokens[] = {
	"and", "break", "do", "else", "elseif",
	"end", "false", "for", "function", "if",
	"in", "local", "nil", "not", "or", "repeat",
	"return", "then", "true", "until", "while",
	"..", "...", "==", ">=", "<=", "~=",
	"<number>", "<name>", "<string>", "<eof>",
	NULL
};

#define save_and_next(ls)(save(ls,ls->current),next(ls))
static void save(LexState * ls, int c)
{
	Mbuffer *b = ls->buff;
	if (b->n + 1 > b->buffsize) {
		size_t newsize;
		if (b->buffsize >= ((size_t)(~(size_t)0) - 2) / 2)
			luaX_lexerror(ls, "lexical element too long", 0);
		newsize = b->buffsize * 2;
		luaZ_resizebuffer(ls->L, b, newsize);
	}
	b->buffer[b->n++] = cast(char, c);
}

static void luaX_init(lua_State * L)
{
	int i;
	for (i = 0; i < (cast(int, TK_WHILE - 257 + 1)); i++) {
		TString *ts = luaS_new(L, luaX_tokens[i]);
		luaS_fix(ts);
		ts->tsv.reserved = cast_byte(i + 1);
	}
}

static const char *luaX_token2str(LexState * ls, int token)
{
	if (token < 257) {
		return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)",
							   token) :
		    luaO_pushfstring(ls->L, "%c", token);
	} else
		return luaX_tokens[token - 257];
}

static const char *txtToken(LexState * ls, int token)
{
	switch (token) {
	case TK_NAME:
	case TK_STRING:
	case TK_NUMBER:
		save(ls, '\0');
		return luaZ_buffer(ls->buff);
	default:
		return luaX_token2str(ls, token);
	}
}

static void luaX_lexerror(LexState * ls, const char *msg, int token)
{
	char buff[80];
	luaO_chunkid(buff, getstr(ls->source), 80);
	msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
	if (token)
		luaO_pushfstring(ls->L, "%s near " LUA_QL("%s"), msg,
				 txtToken(ls, token));
	luaD_throw(ls->L, 3);
}

static void luaX_syntaxerror(LexState * ls, const char *msg)
{
	luaX_lexerror(ls, msg, ls->t.token);
}

static TString *luaX_newstring(LexState * ls, const char *str, size_t l)
{
	lua_State *L = ls->L;
	TString *ts = luaS_newlstr(L, str, l);
	TValue *o = luaH_setstr(L, ls->fs->h, ts);
	if (ttisnil(o)) {
		setbvalue(o, 1);
		luaC_checkGC(L);
	}
	return ts;
}

static void inclinenumber(LexState * ls)
{
	int old = ls->current;
	next(ls);
	if (currIsNewline(ls) && ls->current != old)
		next(ls);
	if (++ls->linenumber >= (INT_MAX - 2))
		luaX_syntaxerror(ls, "chunk has too many lines");
}

static void luaX_setinput(lua_State * L, LexState * ls, ZIO * z,
			  TString * source)
{
	ls->decpoint = '.';
	ls->L = L;
	ls->lookahead.token = TK_EOS;
	ls->z = z;
	ls->fs = NULL;
	ls->linenumber = 1;
	ls->lastline = 1;
	ls->source = source;
	luaZ_resizebuffer(ls->L, ls->buff, 32);
	next(ls);
}

static int check_next(LexState * ls, const char *set)
{
	if (!strchr(set, ls->current))
		return 0;
	save_and_next(ls);
	return 1;
}

static void buffreplace(LexState * ls, char from, char to)
{
	size_t n = luaZ_bufflen(ls->buff);
	char *p = luaZ_buffer(ls->buff);
	while (n--)
		if (p[n] == from)
			p[n] = to;
}

static void read_numeral(LexState * ls, SemInfo * seminfo)
{
	do {
		save_and_next(ls);
	} while (isdigit(ls->current) || ls->current == '.');
	if (check_next(ls, "Ee"))
		check_next(ls, "+-");
	while (isalnum(ls->current) || ls->current == '_')
		save_and_next(ls);
	save(ls, '\0');
	buffreplace(ls, '.', ls->decpoint);
	if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r))
		luaX_lexerror(ls, "malformed number", TK_NUMBER);
}

static int skip_sep(LexState * ls)
{
	int count = 0;
	int s = ls->current;
	save_and_next(ls);
	while (ls->current == '=') {
		save_and_next(ls);
		count++;
	}
	return (ls->current == s) ? count : (-count) - 1;
}

static void read_long_string(LexState * ls, SemInfo * seminfo, int sep)
{
	int cont = 0;
	(void)(cont);
	save_and_next(ls);
	if (currIsNewline(ls))
		inclinenumber(ls);
	for (;;) {
		switch (ls->current) {
		case (-1):
			luaX_lexerror(ls, (seminfo) ? "unfinished long string" :
				      "unfinished long comment", TK_EOS);
			break;
		case ']':{
				if (skip_sep(ls) == sep) {
					save_and_next(ls);
					goto endloop;
				}
				break;
			}
		case '\n':
		case '\r':{
				save(ls, '\n');
				inclinenumber(ls);
				if (!seminfo)
					luaZ_resetbuffer(ls->buff);
				break;
			}
		default:{
				if (seminfo)
					save_and_next(ls);
				else
					next(ls);
			}
		}
	}
 endloop:
	if (seminfo)
		seminfo->ts =
		    luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
				   luaZ_bufflen(ls->buff) - 2 * (2 + sep));
}

static void read_string(LexState * ls, int del, SemInfo * seminfo)
{
	save_and_next(ls);
	while (ls->current != del) {
		switch (ls->current) {
		case (-1):
			luaX_lexerror(ls, "unfinished string", TK_EOS);
			continue;
		case '\n':
		case '\r':
			luaX_lexerror(ls, "unfinished string", TK_STRING);
			continue;
		case '\\':{
				int c;
				next(ls);
				switch (ls->current) {
				case 'a':
					c = '\a';
					break;
				case 'b':
					c = '\b';
					break;
				case 'f':
					c = '\f';
					break;
				case 'n':
					c = '\n';
					break;
				case 'r':
					c = '\r';
					break;
				case 't':
					c = '\t';
					break;
				case 'v':
					c = '\v';
					break;
				case '\n':
				case '\r':
					save(ls, '\n');
					inclinenumber(ls);
					continue;
				case (-1):
					continue;
				default:{
						if (!isdigit(ls->current))
							save_and_next(ls);
						else {
							int i = 0;
							c = 0;
							do {
								c = 10 * c +
								    (ls->
								     current -
								     '0');
								next(ls);
							} while (++i < 3
								 && isdigit(ls->
									    current));
							if (c > UCHAR_MAX)
								luaX_lexerror
								    (ls,
								     "escape sequence too large",
								     TK_STRING);
							save(ls, c);
						}
						continue;
					}
				}
				save(ls, c);
				next(ls);
				continue;
			}
		default:
			save_and_next(ls);
		}
	}
	save_and_next(ls);
	seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,
				     luaZ_bufflen(ls->buff) - 2);
}

static int llex(LexState * ls, SemInfo * seminfo)
{
	luaZ_resetbuffer(ls->buff);
	for (;;) {
		switch (ls->current) {
		case '\n':
		case '\r':{
				inclinenumber(ls);
				continue;
			}
		case '-':{
				next(ls);
				if (ls->current != '-')
					return '-';
				next(ls);
				if (ls->current == '[') {
					int sep = skip_sep(ls);
					luaZ_resetbuffer(ls->buff);
					if (sep >= 0) {
						read_long_string(ls, NULL, sep);
						luaZ_resetbuffer(ls->buff);
						continue;
					}
				}
				while (!currIsNewline(ls)
				       && ls->current != (-1))
					next(ls);
				continue;
			}
		case '[':{
				int sep = skip_sep(ls);
				if (sep >= 0) {
					read_long_string(ls, seminfo, sep);
					return TK_STRING;
				} else if (sep == -1)
					return '[';
				else
					luaX_lexerror(ls,
						      "invalid long string delimiter",
						      TK_STRING);
			}
		case '=':{
				next(ls);
				if (ls->current != '=')
					return '=';
				else {
					next(ls);
					return TK_EQ;
				}
			}
		case '<':{
				next(ls);
				if (ls->current != '=')
					return '<';
				else {
					next(ls);
					return TK_LE;
				}
			}
		case '>':{
				next(ls);
				if (ls->current != '=')
					return '>';
				else {
					next(ls);
					return TK_GE;
				}
			}
		case '~':{
				next(ls);
				if (ls->current != '=')
					return '~';
				else {
					next(ls);
					return TK_NE;
				}
			}
		case '"':
		case '\'':{
				read_string(ls, ls->current, seminfo);
				return TK_STRING;
			}
		case '.':{
				save_and_next(ls);
				if (check_next(ls, ".")) {
					if (check_next(ls, "."))
						return TK_DOTS;
					else
						return TK_CONCAT;
				} else if (!isdigit(ls->current))
					return '.';
				else {
					read_numeral(ls, seminfo);
					return TK_NUMBER;
				}
			}
		case (-1):{
				return TK_EOS;
			}
		default:{
				if (isspace(ls->current)) {
					next(ls);
					continue;
				} else if (isdigit(ls->current)) {
					read_numeral(ls, seminfo);
					return TK_NUMBER;
				} else if (isalpha(ls->current)
					   || ls->current == '_') {
					TString *ts;
					do {
						save_and_next(ls);
					} while (isalnum(ls->current)
						 || ls->current == '_');
					ts = luaX_newstring(ls,
							    luaZ_buffer(ls->
									buff),
							    luaZ_bufflen(ls->
									 buff));
					if (ts->tsv.reserved > 0)
						return ts->tsv.reserved - 1 +
						    257;
					else {
						seminfo->ts = ts;
						return TK_NAME;
					}
				} else {
					int c = ls->current;
					next(ls);
					return c;
				}
			}
		}
	}
}

static void luaX_next(LexState * ls)
{
	ls->lastline = ls->linenumber;
	if (ls->lookahead.token != TK_EOS) {
		ls->t = ls->lookahead;
		ls->lookahead.token = TK_EOS;
	} else
		ls->t.token = llex(ls, &ls->t.seminfo);
}

static void luaX_lookahead(LexState * ls)
{
	ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
}

#define hasjumps(e)((e)->t!=(e)->f)
static int isnumeral(expdesc * e)
{
	return (e->k == VKNUM && e->t == (-1) && e->f == (-1));
}

static void luaK_nil(FuncState * fs, int from, int n)
{
	Instruction *previous;
	if (fs->pc > fs->lasttarget) {
		if (fs->pc == 0) {
			if (from >= fs->nactvar)
				return;
		} else {
			previous = &fs->f->code[fs->pc - 1];
			if (GET_OPCODE(*previous) == OP_LOADNIL) {
				int pfrom = GETARG_A(*previous);
				int pto = GETARG_B(*previous);
				if (pfrom <= from && from <= pto + 1) {
					if (from + n - 1 > pto)
						SETARG_B(*previous,
							 from + n - 1);
					return;
				}
			}
		}
	}
	luaK_codeABC(fs, OP_LOADNIL, from, from + n - 1, 0);
}

static int luaK_jump(FuncState * fs)
{
	int jpc = fs->jpc;
	int j;
	fs->jpc = (-1);
	j = luaK_codeAsBx(fs, OP_JMP, 0, (-1));
	luaK_concat(fs, &j, jpc);
	return j;
}

static void luaK_ret(FuncState * fs, int first, int nret)
{
	luaK_codeABC(fs, OP_RETURN, first, nret + 1, 0);
}

static int condjump(FuncState * fs, OpCode op, int A, int B, int C)
{
	luaK_codeABC(fs, op, A, B, C);
	return luaK_jump(fs);
}

static void fixjump(FuncState * fs, int pc, int dest)
{
	Instruction *jmp = &fs->f->code[pc];
	int offset = dest - (pc + 1);
	if (abs(offset) > (((1 << (9 + 9)) - 1) >> 1))
		luaX_syntaxerror(fs->ls, "control structure too long");
	SETARG_sBx(*jmp, offset);
}

static int luaK_getlabel(FuncState * fs)
{
	fs->lasttarget = fs->pc;
	return fs->pc;
}

static int getjump(FuncState * fs, int pc)
{
	int offset = GETARG_sBx(fs->f->code[pc]);
	if (offset == (-1))
		return (-1);
	else
		return (pc + 1) + offset;
}

static Instruction *getjumpcontrol(FuncState * fs, int pc)
{
	Instruction *pi = &fs->f->code[pc];
	if (pc >= 1 && testTMode(GET_OPCODE(*(pi - 1))))
		return pi - 1;
	else
		return pi;
}

static int need_value(FuncState * fs, int list)
{
	for (; list != (-1); list = getjump(fs, list)) {
		Instruction i = *getjumpcontrol(fs, list);
		if (GET_OPCODE(i) != OP_TESTSET)
			return 1;
	}
	return 0;
}

static int patchtestreg(FuncState * fs, int node, int reg)
{
	Instruction *i = getjumpcontrol(fs, node);
	if (GET_OPCODE(*i) != OP_TESTSET)
		return 0;
	if (reg != ((1 << 8) - 1) && reg != GETARG_B(*i))
		SETARG_A(*i, reg);
	else
		*i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
	return 1;
}

static void removevalues(FuncState * fs, int list)
{
	for (; list != (-1); list = getjump(fs, list))
		patchtestreg(fs, list, ((1 << 8) - 1));
}

static void patchlistaux(FuncState * fs, int list, int vtarget, int reg,
			 int dtarget)
{
	while (list != (-1)) {
		int next = getjump(fs, list);
		if (patchtestreg(fs, list, reg))
			fixjump(fs, list, vtarget);
		else
			fixjump(fs, list, dtarget);
		list = next;
	}
}

static void dischargejpc(FuncState * fs)
{
	patchlistaux(fs, fs->jpc, fs->pc, ((1 << 8) - 1), fs->pc);
	fs->jpc = (-1);
}

static void luaK_patchlist(FuncState * fs, int list, int target)
{
	if (target == fs->pc)
		luaK_patchtohere(fs, list);
	else {
		patchlistaux(fs, list, target, ((1 << 8) - 1), target);
	}
}

static void luaK_patchtohere(FuncState * fs, int list)
{
	luaK_getlabel(fs);
	luaK_concat(fs, &fs->jpc, list);
}

static void luaK_concat(FuncState * fs, int *l1, int l2)
{
	if (l2 == (-1))
		return;
	else if (*l1 == (-1))
		*l1 = l2;
	else {
		int list = *l1;
		int next;
		while ((next = getjump(fs, list)) != (-1))
			list = next;
		fixjump(fs, list, l2);
	}
}

static void luaK_checkstack(FuncState * fs, int n)
{
	int newstack = fs->freereg + n;
	if (newstack > fs->f->maxstacksize) {
		if (newstack >= 250)
			luaX_syntaxerror(fs->ls,
					 "function or expression too complex");
		fs->f->maxstacksize = cast_byte(newstack);
	}
}

static void luaK_reserveregs(FuncState * fs, int n)
{
	luaK_checkstack(fs, n);
	fs->freereg += n;
}

static void freereg(FuncState * fs, int reg)
{
	if (!ISK(reg) && reg >= fs->nactvar) {
		fs->freereg--;
	}
}

static void freeexp(FuncState * fs, expdesc * e)
{
	if (e->k == VNONRELOC)
		freereg(fs, e->u.s.info);
}

static int addk(FuncState * fs, TValue * k, TValue * v)
{
	lua_State *L = fs->L;
	TValue *idx = luaH_set(L, fs->h, k);
	Proto *f = fs->f;
	int oldsize = f->sizek;
	if (ttisnumber(idx)) {
		return cast_int(nvalue(idx));
	} else {
		setnvalue(idx, cast_num(fs->nk));
		luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
				((1 << (9 + 9)) - 1),
				"constant table overflow");
		while (oldsize < f->sizek)
			setnilvalue(&f->k[oldsize++]);
		setobj(L, &f->k[fs->nk], v);
		luaC_barrier(L, f, v);
		return fs->nk++;
	}
}

static int luaK_stringK(FuncState * fs, TString * s)
{
	TValue o;
	setsvalue(fs->L, &o, s);
	return addk(fs, &o, &o);
}

static int luaK_numberK(FuncState * fs, lua_Number r)
{
	TValue o;
	setnvalue(&o, r);
	return addk(fs, &o, &o);
}

static int boolK(FuncState * fs, int b)
{
	TValue o;
	setbvalue(&o, b);
	return addk(fs, &o, &o);
}

static int nilK(FuncState * fs)
{
	TValue k, v;
	setnilvalue(&v);
	sethvalue(fs->L, &k, fs->h);
	return addk(fs, &k, &v);
}

static void luaK_setreturns(FuncState * fs, expdesc * e, int nresults)
{
	if (e->k == VCALL) {
		SETARG_C(getcode(fs, e), nresults + 1);
	} else if (e->k == VVARARG) {
		SETARG_B(getcode(fs, e), nresults + 1);
		SETARG_A(getcode(fs, e), fs->freereg);
		luaK_reserveregs(fs, 1);
	}
}

static void luaK_setoneret(FuncState * fs, expdesc * e)
{
	if (e->k == VCALL) {
		e->k = VNONRELOC;
		e->u.s.info = GETARG_A(getcode(fs, e));
	} else if (e->k == VVARARG) {
		SETARG_B(getcode(fs, e), 2);
		e->k = VRELOCABLE;
	}
}

static void luaK_dischargevars(FuncState * fs, expdesc * e)
{
	switch (e->k) {
	case VLOCAL:{
			e->k = VNONRELOC;
			break;
		}
	case VUPVAL:{
			e->u.s.info =
			    luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
			e->k = VRELOCABLE;
			break;
		}
	case VGLOBAL:{
			e->u.s.info =
			    luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
			e->k = VRELOCABLE;
			break;
		}
	case VINDEXED:{
			freereg(fs, e->u.s.aux);
			freereg(fs, e->u.s.info);
			e->u.s.info =
			    luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info,
					 e->u.s.aux);
			e->k = VRELOCABLE;
			break;
		}
	case VVARARG:
	case VCALL:{
			luaK_setoneret(fs, e);
			break;
		}
	default:
		break;
	}
}

static int code_label(FuncState * fs, int A, int b, int jump)
{
	luaK_getlabel(fs);
	return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
}

static void discharge2reg(FuncState * fs, expdesc * e, int reg)
{
	luaK_dischargevars(fs, e);
	switch (e->k) {
	case VNIL:{
			luaK_nil(fs, reg, 1);
			break;
		}
	case VFALSE:
	case VTRUE:{
			luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
			break;
		}
	case VK:{
			luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);
			break;
		}
	case VKNUM:{
			luaK_codeABx(fs, OP_LOADK, reg,
				     luaK_numberK(fs, e->u.nval));
			break;
		}
	case VRELOCABLE:{
			Instruction *pc = &getcode(fs, e);
			SETARG_A(*pc, reg);
			break;
		}
	case VNONRELOC:{
			if (reg != e->u.s.info)
				luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
			break;
		}
	default:{
			return;
		}
	}
	e->u.s.info = reg;
	e->k = VNONRELOC;
}

static void discharge2anyreg(FuncState * fs, expdesc * e)
{
	if (e->k != VNONRELOC) {
		luaK_reserveregs(fs, 1);
		discharge2reg(fs, e, fs->freereg - 1);
	}
}

static void exp2reg(FuncState * fs, expdesc * e, int reg)
{
	discharge2reg(fs, e, reg);
	if (e->k == VJMP)
		luaK_concat(fs, &e->t, e->u.s.info);
	if (hasjumps(e)) {
		int final;
		int p_f = (-1);
		int p_t = (-1);
		if (need_value(fs, e->t) || need_value(fs, e->f)) {
			int fj = (e->k == VJMP) ? (-1) : luaK_jump(fs);
			p_f = code_label(fs, reg, 0, 1);
			p_t = code_label(fs, reg, 1, 0);
			luaK_patchtohere(fs, fj);
		}
		final = luaK_getlabel(fs);
		patchlistaux(fs, e->f, final, reg, p_f);
		patchlistaux(fs, e->t, final, reg, p_t);
	}
	e->f = e->t = (-1);
	e->u.s.info = reg;
	e->k = VNONRELOC;
}

static void luaK_exp2nextreg(FuncState * fs, expdesc * e)
{
	luaK_dischargevars(fs, e);
	freeexp(fs, e);
	luaK_reserveregs(fs, 1);
	exp2reg(fs, e, fs->freereg - 1);
}

static int luaK_exp2anyreg(FuncState * fs, expdesc * e)
{
	luaK_dischargevars(fs, e);
	if (e->k == VNONRELOC) {
		if (!hasjumps(e))
			return e->u.s.info;
		if (e->u.s.info >= fs->nactvar) {
			exp2reg(fs, e, e->u.s.info);
			return e->u.s.info;
		}
	}
	luaK_exp2nextreg(fs, e);
	return e->u.s.info;
}

static void luaK_exp2val(FuncState * fs, expdesc * e)
{
	if (hasjumps(e))
		luaK_exp2anyreg(fs, e);
	else
		luaK_dischargevars(fs, e);
}

static int luaK_exp2RK(FuncState * fs, expdesc * e)
{
	luaK_exp2val(fs, e);
	switch (e->k) {
	case VKNUM:
	case VTRUE:
	case VFALSE:
	case VNIL:{
			if (fs->nk <= ((1 << (9 - 1)) - 1)) {
				e->u.s.info = (e->k == VNIL) ? nilK(fs) :
				    (e->k == VKNUM) ? luaK_numberK(fs,
								   e->u.
								   nval) :
				    boolK(fs, (e->k == VTRUE));
				e->k = VK;
				return RKASK(e->u.s.info);
			} else
				break;
		}
	case VK:{
			if (e->u.s.info <= ((1 << (9 - 1)) - 1))
				return RKASK(e->u.s.info);
			else
				break;
		}
	default:
		break;
	}
	return luaK_exp2anyreg(fs, e);
}

static void luaK_storevar(FuncState * fs, expdesc * var, expdesc * ex)
{
	switch (var->k) {
	case VLOCAL:{
			freeexp(fs, ex);
			exp2reg(fs, ex, var->u.s.info);
			return;
		}
	case VUPVAL:{
			int e = luaK_exp2anyreg(fs, ex);
			luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
			break;
		}
	case VGLOBAL:{
			int e = luaK_exp2anyreg(fs, ex);
			luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
			break;
		}
	case VINDEXED:{
			int e = luaK_exp2RK(fs, ex);
			luaK_codeABC(fs, OP_SETTABLE, var->u.s.info,
				     var->u.s.aux, e);
			break;
		}
	default:{
			break;
		}
	}
	freeexp(fs, ex);
}

static void luaK_self(FuncState * fs, expdesc * e, expdesc * key)
{
	int func;
	luaK_exp2anyreg(fs, e);
	freeexp(fs, e);
	func = fs->freereg;
	luaK_reserveregs(fs, 2);
	luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
	freeexp(fs, key);
	e->u.s.info = func;
	e->k = VNONRELOC;
}

static void invertjump(FuncState * fs, expdesc * e)
{
	Instruction *pc = getjumpcontrol(fs, e->u.s.info);
	SETARG_A(*pc, !(GETARG_A(*pc)));
}

static int jumponcond(FuncState * fs, expdesc * e, int cond)
{
	if (e->k == VRELOCABLE) {
		Instruction ie = getcode(fs, e);
		if (GET_OPCODE(ie) == OP_NOT) {
			fs->pc--;
			return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
		}
	}
	discharge2anyreg(fs, e);
	freeexp(fs, e);
	return condjump(fs, OP_TESTSET, ((1 << 8) - 1), e->u.s.info, cond);
}

static void luaK_goiftrue(FuncState * fs, expdesc * e)
{
	int pc;
	luaK_dischargevars(fs, e);
	switch (e->k) {
	case VK:
	case VKNUM:
	case VTRUE:{
			pc = (-1);
			break;
		}
	case VJMP:{
			invertjump(fs, e);
			pc = e->u.s.info;
			break;
		}
	default:{
			pc = jumponcond(fs, e, 0);
			break;
		}
	}
	luaK_concat(fs, &e->f, pc);
	luaK_patchtohere(fs, e->t);
	e->t = (-1);
}

static void luaK_goiffalse(FuncState * fs, expdesc * e)
{
	int pc;
	luaK_dischargevars(fs, e);
	switch (e->k) {
	case VNIL:
	case VFALSE:{
			pc = (-1);
			break;
		}
	case VJMP:{
			pc = e->u.s.info;
			break;
		}
	default:{
			pc = jumponcond(fs, e, 1);
			break;
		}
	}
	luaK_concat(fs, &e->t, pc);
	luaK_patchtohere(fs, e->f);
	e->f = (-1);
}

static void codenot(FuncState * fs, expdesc * e)
{
	luaK_dischargevars(fs, e);
	switch (e->k) {
	case VNIL:
	case VFALSE:{
			e->k = VTRUE;
			break;
		}
	case VK:
	case VKNUM:
	case VTRUE:{
			e->k = VFALSE;
			break;
		}
	case VJMP:{
			invertjump(fs, e);
			break;
		}
	case VRELOCABLE:
	case VNONRELOC:{
			discharge2anyreg(fs, e);
			freeexp(fs, e);
			e->u.s.info =
			    luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);
			e->k = VRELOCABLE;
			break;
		}
	default:{
			break;
		}
	}
	{
		int temp = e->f;
		e->f = e->t;
		e->t = temp;
	}
	removevalues(fs, e->f);
	removevalues(fs, e->t);
}

static void luaK_indexed(FuncState * fs, expdesc * t, expdesc * k)
{
	t->u.s.aux = luaK_exp2RK(fs, k);
	t->k = VINDEXED;
}

static int constfolding(OpCode op, expdesc * e1, expdesc * e2)
{
	lua_Number v1, v2, r;
	if (!isnumeral(e1) || !isnumeral(e2))
		return 0;
	v1 = e1->u.nval;
	v2 = e2->u.nval;
	switch (op) {
	case OP_ADD:
		r = luai_numadd(v1, v2);
		break;
	case OP_SUB:
		r = luai_numsub(v1, v2);
		break;
	case OP_MUL:
		r = luai_nummul(v1, v2);
		break;
	case OP_DIV:
		if (v2 == 0)
			return 0;
		r = luai_numdiv(v1, v2);
		break;
	case OP_MOD:
		if (v2 == 0)
			return 0;
		r = luai_nummod(v1, v2);
		break;
	case OP_POW:
		r = luai_numpow(v1, v2);
		break;
	case OP_UNM:
		r = luai_numunm(v1);
		break;
	case OP_LEN:
		return 0;
	default:
		r = 0;
		break;
	}
	if (luai_numisnan(r))
		return 0;
	e1->u.nval = r;
	return 1;
}

static void codearith(FuncState * fs, OpCode op, expdesc * e1, expdesc * e2)
{
	if (constfolding(op, e1, e2))
		return;
	else {
		int o2 = (op != OP_UNM
			  && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
		int o1 = luaK_exp2RK(fs, e1);
		if (o1 > o2) {
			freeexp(fs, e1);
			freeexp(fs, e2);
		} else {
			freeexp(fs, e2);
			freeexp(fs, e1);
		}
		e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
		e1->k = VRELOCABLE;
	}
}

static void codecomp(FuncState * fs, OpCode op, int cond, expdesc * e1,
		     expdesc * e2)
{
	int o1 = luaK_exp2RK(fs, e1);
	int o2 = luaK_exp2RK(fs, e2);
	freeexp(fs, e2);
	freeexp(fs, e1);
	if (cond == 0 && op != OP_EQ) {
		int temp;
		temp = o1;
		o1 = o2;
		o2 = temp;
		cond = 1;
	}
	e1->u.s.info = condjump(fs, op, cond, o1, o2);
	e1->k = VJMP;
}

static void luaK_prefix(FuncState * fs, UnOpr op, expdesc * e)
{
	expdesc e2;
	e2.t = e2.f = (-1);
	e2.k = VKNUM;
	e2.u.nval = 0;
	switch (op) {
	case OPR_MINUS:{
			if (!isnumeral(e))
				luaK_exp2anyreg(fs, e);
			codearith(fs, OP_UNM, e, &e2);
			break;
		}
	case OPR_NOT:
		codenot(fs, e);
		break;
	case OPR_LEN:{
			luaK_exp2anyreg(fs, e);
			codearith(fs, OP_LEN, e, &e2);
			break;
		}
	default:;
	}
}

static void luaK_infix(FuncState * fs, BinOpr op, expdesc * v)
{
	switch (op) {
	case OPR_AND:{
			luaK_goiftrue(fs, v);
			break;
		}
	case OPR_OR:{
			luaK_goiffalse(fs, v);
			break;
		}
	case OPR_CONCAT:{
			luaK_exp2nextreg(fs, v);
			break;
		}
	case OPR_ADD:
	case OPR_SUB:
	case OPR_MUL:
	case OPR_DIV:
	case OPR_MOD:
	case OPR_POW:{
			if (!isnumeral(v))
				luaK_exp2RK(fs, v);
			break;
		}
	default:{
			luaK_exp2RK(fs, v);
			break;
		}
	}
}

static void luaK_posfix(FuncState * fs, BinOpr op, expdesc * e1, expdesc * e2)
{
	switch (op) {
	case OPR_AND:{
			luaK_dischargevars(fs, e2);
			luaK_concat(fs, &e2->f, e1->f);
			*e1 = *e2;
			break;
		}
	case OPR_OR:{
			luaK_dischargevars(fs, e2);
			luaK_concat(fs, &e2->t, e1->t);
			*e1 = *e2;
			break;
		}
	case OPR_CONCAT:{
			luaK_exp2val(fs, e2);
			if (e2->k == VRELOCABLE
			    && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
				freeexp(fs, e1);
				SETARG_B(getcode(fs, e2), e1->u.s.info);
				e1->k = VRELOCABLE;
				e1->u.s.info = e2->u.s.info;
			} else {
				luaK_exp2nextreg(fs, e2);
				codearith(fs, OP_CONCAT, e1, e2);
			}
			break;
		}
	case OPR_ADD:
		codearith(fs, OP_ADD, e1, e2);
		break;
	case OPR_SUB:
		codearith(fs, OP_SUB, e1, e2);
		break;
	case OPR_MUL:
		codearith(fs, OP_MUL, e1, e2);
		break;
	case OPR_DIV:
		codearith(fs, OP_DIV, e1, e2);
		break;
	case OPR_MOD:
		codearith(fs, OP_MOD, e1, e2);
		break;
	case OPR_POW:
		codearith(fs, OP_POW, e1, e2);
		break;
	case OPR_EQ:
		codecomp(fs, OP_EQ, 1, e1, e2);
		break;
	case OPR_NE:
		codecomp(fs, OP_EQ, 0, e1, e2);
		break;
	case OPR_LT:
		codecomp(fs, OP_LT, 1, e1, e2);
		break;
	case OPR_LE:
		codecomp(fs, OP_LE, 1, e1, e2);
		break;
	case OPR_GT:
		codecomp(fs, OP_LT, 0, e1, e2);
		break;
	case OPR_GE:
		codecomp(fs, OP_LE, 0, e1, e2);
		break;
	default:;
	}
}

static void luaK_fixline(FuncState * fs, int line)
{
	fs->f->lineinfo[fs->pc - 1] = line;
}

static int luaK_code(FuncState * fs, Instruction i, int line)
{
	Proto *f = fs->f;
	dischargejpc(fs);
	luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
			(INT_MAX - 2), "code size overflow");
	f->code[fs->pc] = i;
	luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
			(INT_MAX - 2), "code size overflow");
	f->lineinfo[fs->pc] = line;
	return fs->pc++;
}

static int luaK_codeABC(FuncState * fs, OpCode o, int a, int b, int c)
{
	return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
}

static int luaK_codeABx(FuncState * fs, OpCode o, int a, unsigned int bc)
{
	return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
}

static void luaK_setlist(FuncState * fs, int base, int nelems, int tostore)
{
	int c = (nelems - 1) / 50 + 1;
	int b = (tostore == (-1)) ? 0 : tostore;
	if (c <= ((1 << 9) - 1))
		luaK_codeABC(fs, OP_SETLIST, base, b, c);
	else {
		luaK_codeABC(fs, OP_SETLIST, base, b, 0);
		luaK_code(fs, cast(Instruction, c), fs->ls->lastline);
	}
	fs->freereg = base + 1;
}

#define hasmultret(k)((k)==VCALL||(k)==VVARARG)
#define getlocvar(fs,i)((fs)->f->locvars[(fs)->actvar[i]])
#define luaY_checklimit(fs,v,l,m)if((v)>(l))errorlimit(fs,l,m)
typedef struct BlockCnt {
	struct BlockCnt *previous;
	int breaklist;
	lu_byte nactvar;
	lu_byte upval;
	lu_byte isbreakable;
} BlockCnt;
static void chunk(LexState * ls);
static void expr(LexState * ls, expdesc * v);
static void anchor_token(LexState * ls)
{
	if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
		TString *ts = ls->t.seminfo.ts;
		luaX_newstring(ls, getstr(ts), ts->tsv.len);
	}
}

static void error_expected(LexState * ls, int token)
{
	luaX_syntaxerror(ls,
			 luaO_pushfstring(ls->L, LUA_QL("%s") " expected",
					  luaX_token2str(ls, token)));
}

static void errorlimit(FuncState * fs, int limit, const char *what)
{
	const char *msg = (fs->f->linedefined == 0) ?
	    luaO_pushfstring(fs->L, "main function has more than %d %s", limit,
			     what) : luaO_pushfstring(fs->L,
						      "function at line %d has more than %d %s",
						      fs->f->linedefined, limit,
						      what);
	luaX_lexerror(fs->ls, msg, 0);
}

static int testnext(LexState * ls, int c)
{
	if (ls->t.token == c) {
		luaX_next(ls);
		return 1;
	} else
		return 0;
}

static void check(LexState * ls, int c)
{
	if (ls->t.token != c)
		error_expected(ls, c);
}

static void checknext(LexState * ls, int c)
{
	check(ls, c);
	luaX_next(ls);
}

#define check_condition(ls,c,msg){if(!(c))luaX_syntaxerror(ls,msg);}
static void check_match(LexState * ls, int what, int who, int where)
{
	if (!testnext(ls, what)) {
		if (where == ls->linenumber)
			error_expected(ls, what);
		else {
			luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
							      LUA_QL("%s")
							      " expected (to close "
							      LUA_QL("%s")
							      " at line %d)",
							      luaX_token2str(ls,
									     what),
							      luaX_token2str(ls,
									     who),
							      where));
		}
	}
}

static TString *str_checkname(LexState * ls)
{
	TString *ts;
	check(ls, TK_NAME);
	ts = ls->t.seminfo.ts;
	luaX_next(ls);
	return ts;
}

static void init_exp(expdesc * e, expkind k, int i)
{
	e->f = e->t = (-1);
	e->k = k;
	e->u.s.info = i;
}

static void codestring(LexState * ls, expdesc * e, TString * s)
{
	init_exp(e, VK, luaK_stringK(ls->fs, s));
}

static void checkname(LexState * ls, expdesc * e)
{
	codestring(ls, e, str_checkname(ls));
}

static int registerlocalvar(LexState * ls, TString * varname)
{
	FuncState *fs = ls->fs;
	Proto *f = fs->f;
	int oldsize = f->sizelocvars;
	luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
			LocVar, SHRT_MAX, "too many local variables");
	while (oldsize < f->sizelocvars)
		f->locvars[oldsize++].varname = NULL;
	f->locvars[fs->nlocvars].varname = varname;
	luaC_objbarrier(ls->L, f, varname);
	return fs->nlocvars++;
}

#define new_localvarliteral(ls,v,n)new_localvar(ls,luaX_newstring(ls,""v,(sizeof(v)/sizeof(char))-1),n)
static void new_localvar(LexState * ls, TString * name, int n)
{
	FuncState *fs = ls->fs;
	luaY_checklimit(fs, fs->nactvar + n + 1, 200, "local variables");
	fs->actvar[fs->nactvar + n] =
	    cast(unsigned short, registerlocalvar(ls, name));
}

static void adjustlocalvars(LexState * ls, int nvars)
{
	FuncState *fs = ls->fs;
	fs->nactvar = cast_byte(fs->nactvar + nvars);
	for (; nvars; nvars--) {
		getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;
	}
}

static void removevars(LexState * ls, int tolevel)
{
	FuncState *fs = ls->fs;
	while (fs->nactvar > tolevel)
		getlocvar(fs, --fs->nactvar).endpc = fs->pc;
}

static int indexupvalue(FuncState * fs, TString * name, expdesc * v)
{
	int i;
	Proto *f = fs->f;
	int oldsize = f->sizeupvalues;
	for (i = 0; i < f->nups; i++) {
		if (fs->upvalues[i].k == v->k
		    && fs->upvalues[i].info == v->u.s.info) {
			return i;
		}
	}
	luaY_checklimit(fs, f->nups + 1, 60, "upvalues");
	luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,
			TString *, (INT_MAX - 2), "");
	while (oldsize < f->sizeupvalues)
		f->upvalues[oldsize++] = NULL;
	f->upvalues[f->nups] = name;
	luaC_objbarrier(fs->L, f, name);
	fs->upvalues[f->nups].k = cast_byte(v->k);
	fs->upvalues[f->nups].info = cast_byte(v->u.s.info);
	return f->nups++;
}

static int searchvar(FuncState * fs, TString * n)
{
	int i;
	for (i = fs->nactvar - 1; i >= 0; i--) {
		if (n == getlocvar(fs, i).varname)
			return i;
	}
	return -1;
}

static void markupval(FuncState * fs, int level)
{
	BlockCnt *bl = fs->bl;
	while (bl && bl->nactvar > level)
		bl = bl->previous;
	if (bl)
		bl->upval = 1;
}

static int singlevaraux(FuncState * fs, TString * n, expdesc * var, int base)
{
	if (fs == NULL) {
		init_exp(var, VGLOBAL, ((1 << 8) - 1));
		return VGLOBAL;
	} else {
		int v = searchvar(fs, n);
		if (v >= 0) {
			init_exp(var, VLOCAL, v);
			if (!base)
				markupval(fs, v);
			return VLOCAL;
		} else {
			if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL)
				return VGLOBAL;
			var->u.s.info = indexupvalue(fs, n, var);
			var->k = VUPVAL;
			return VUPVAL;
		}
	}
}

static void singlevar(LexState * ls, expdesc * var)
{
	TString *varname = str_checkname(ls);
	FuncState *fs = ls->fs;
	if (singlevaraux(fs, varname, var, 1) == VGLOBAL)
		var->u.s.info = luaK_stringK(fs, varname);
}

static void adjust_assign(LexState * ls, int nvars, int nexps, expdesc * e)
{
	FuncState *fs = ls->fs;
	int extra = nvars - nexps;
	if (hasmultret(e->k)) {
		extra++;
		if (extra < 0)
			extra = 0;
		luaK_setreturns(fs, e, extra);
		if (extra > 1)
			luaK_reserveregs(fs, extra - 1);
	} else {
		if (e->k != VVOID)
			luaK_exp2nextreg(fs, e);
		if (extra > 0) {
			int reg = fs->freereg;
			luaK_reserveregs(fs, extra);
			luaK_nil(fs, reg, extra);
		}
	}
}

static void enterlevel(LexState * ls)
{
	if (++ls->L->nCcalls > 200)
		luaX_lexerror(ls, "chunk has too many syntax levels", 0);
}

#define leavelevel(ls)((ls)->L->nCcalls--)
static void enterblock(FuncState * fs, BlockCnt * bl, lu_byte isbreakable)
{
	bl->breaklist = (-1);
	bl->isbreakable = isbreakable;
	bl->nactvar = fs->nactvar;
	bl->upval = 0;
	bl->previous = fs->bl;
	fs->bl = bl;
}

static void leaveblock(FuncState * fs)
{
	BlockCnt *bl = fs->bl;
	fs->bl = bl->previous;
	removevars(fs->ls, bl->nactvar);
	if (bl->upval)
		luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
	fs->freereg = fs->nactvar;
	luaK_patchtohere(fs, bl->breaklist);
}

static void pushclosure(LexState * ls, FuncState * func, expdesc * v)
{
	FuncState *fs = ls->fs;
	Proto *f = fs->f;
	int oldsize = f->sizep;
	int i;
	luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
			((1 << (9 + 9)) - 1), "constant table overflow");
	while (oldsize < f->sizep)
		f->p[oldsize++] = NULL;
	f->p[fs->np++] = func->f;
	luaC_objbarrier(ls->L, f, func->f);
	init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1));
	for (i = 0; i < func->f->nups; i++) {
		OpCode o =
		    (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
		luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);
	}
}

static void open_func(LexState * ls, FuncState * fs)
{
	lua_State *L = ls->L;
	Proto *f = luaF_newproto(L);
	fs->f = f;
	fs->prev = ls->fs;
	fs->ls = ls;
	fs->L = L;
	ls->fs = fs;
	fs->pc = 0;
	fs->lasttarget = -1;
	fs->jpc = (-1);
	fs->freereg = 0;
	fs->nk = 0;
	fs->np = 0;
	fs->nlocvars = 0;
	fs->nactvar = 0;
	fs->bl = NULL;
	f->source = ls->source;
	f->maxstacksize = 2;
	fs->h = luaH_new(L, 0, 0);
	sethvalue(L, L->top, fs->h);
	incr_top(L);
	setptvalue(L, L->top, f);
	incr_top(L);
}

static void close_func(LexState * ls)
{
	lua_State *L = ls->L;
	FuncState *fs = ls->fs;
	Proto *f = fs->f;
	removevars(ls, 0);
	luaK_ret(fs, 0, 0);
	luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
	f->sizecode = fs->pc;
	luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
	f->sizelineinfo = fs->pc;
	luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);
	f->sizek = fs->nk;
	luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
	f->sizep = fs->np;
	luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
	f->sizelocvars = fs->nlocvars;
	luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);
	f->sizeupvalues = f->nups;
	ls->fs = fs->prev;
	if (fs)
		anchor_token(ls);
	L->top -= 2;
}

static Proto *luaY_parser(lua_State * L, ZIO * z, Mbuffer * buff,
			  const char *name)
{
	struct LexState lexstate;
	struct FuncState funcstate;
	lexstate.buff = buff;
	luaX_setinput(L, &lexstate, z, luaS_new(L, name));
	open_func(&lexstate, &funcstate);
	funcstate.f->is_vararg = 2;
	luaX_next(&lexstate);
	chunk(&lexstate);
	check(&lexstate, TK_EOS);
	close_func(&lexstate);
	return funcstate.f;
}

static void field(LexState * ls, expdesc * v)
{
	FuncState *fs = ls->fs;
	expdesc key;
	luaK_exp2anyreg(fs, v);
	luaX_next(ls);
	checkname(ls, &key);
	luaK_indexed(fs, v, &key);
}

static void yindex(LexState * ls, expdesc * v)
{
	luaX_next(ls);
	expr(ls, v);
	luaK_exp2val(ls->fs, v);
	checknext(ls, ']');
}

struct ConsControl {
	expdesc v;
	expdesc *t;
	int nh;
	int na;
	int tostore;
};
static void recfield(LexState * ls, struct ConsControl *cc)
{
	FuncState *fs = ls->fs;
	int reg = ls->fs->freereg;
	expdesc key, val;
	int rkkey;
	if (ls->t.token == TK_NAME) {
		luaY_checklimit(fs, cc->nh, (INT_MAX - 2),
				"items in a constructor");
		checkname(ls, &key);
	} else
		yindex(ls, &key);
	cc->nh++;
	checknext(ls, '=');
	rkkey = luaK_exp2RK(fs, &key);
	expr(ls, &val);
	luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey,
		     luaK_exp2RK(fs, &val));
	fs->freereg = reg;
}

static void closelistfield(FuncState * fs, struct ConsControl *cc)
{
	if (cc->v.k == VVOID)
		return;
	luaK_exp2nextreg(fs, &cc->v);
	cc->v.k = VVOID;
	if (cc->tostore == 50) {
		luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);
		cc->tostore = 0;
	}
}

static void lastlistfield(FuncState * fs, struct ConsControl *cc)
{
	if (cc->tostore == 0)
		return;
	if (hasmultret(cc->v.k)) {
		luaK_setmultret(fs, &cc->v);
		luaK_setlist(fs, cc->t->u.s.info, cc->na, (-1));
		cc->na--;
	} else {
		if (cc->v.k != VVOID)
			luaK_exp2nextreg(fs, &cc->v);
		luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);
	}
}

static void listfield(LexState * ls, struct ConsControl *cc)
{
	expr(ls, &cc->v);
	luaY_checklimit(ls->fs, cc->na, (INT_MAX - 2),
			"items in a constructor");
	cc->na++;
	cc->tostore++;
}

static void constructor(LexState * ls, expdesc * t)
{
	FuncState *fs = ls->fs;
	int line = ls->linenumber;
	int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
	struct ConsControl cc;
	cc.na = cc.nh = cc.tostore = 0;
	cc.t = t;
	init_exp(t, VRELOCABLE, pc);
	init_exp(&cc.v, VVOID, 0);
	luaK_exp2nextreg(ls->fs, t);
	checknext(ls, '{');
	do {
		if (ls->t.token == '}')
			break;
		closelistfield(fs, &cc);
		switch (ls->t.token) {
		case TK_NAME:{
				luaX_lookahead(ls);
				if (ls->lookahead.token != '=')
					listfield(ls, &cc);
				else
					recfield(ls, &cc);
				break;
			}
		case '[':{
				recfield(ls, &cc);
				break;
			}
		default:{
				listfield(ls, &cc);
				break;
			}
		}
	} while (testnext(ls, ',') || testnext(ls, ';'));
	check_match(ls, '}', '{', line);
	lastlistfield(fs, &cc);
	SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na));
	SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh));
}

static void parlist(LexState * ls)
{
	FuncState *fs = ls->fs;
	Proto *f = fs->f;
	int nparams = 0;
	f->is_vararg = 0;
	if (ls->t.token != ')') {
		do {
			switch (ls->t.token) {
			case TK_NAME:{
					new_localvar(ls, str_checkname(ls),
						     nparams++);
					break;
				}
			case TK_DOTS:{
					luaX_next(ls);
					f->is_vararg |= 2;
					break;
				}
			default:
				luaX_syntaxerror(ls,
						 "<name> or " LUA_QL("...")
						 " expected");
			}
		} while (!f->is_vararg && testnext(ls, ','));
	}
	adjustlocalvars(ls, nparams);
	f->numparams = cast_byte(fs->nactvar - (f->is_vararg & 1));
	luaK_reserveregs(fs, fs->nactvar);
}

static void body(LexState * ls, expdesc * e, int needself, int line)
{
	FuncState new_fs;
	open_func(ls, &new_fs);
	new_fs.f->linedefined = line;
	checknext(ls, '(');
	if (needself) {
		new_localvarliteral(ls, "self", 0);
		adjustlocalvars(ls, 1);
	}
	parlist(ls);
	checknext(ls, ')');
	chunk(ls);
	new_fs.f->lastlinedefined = ls->linenumber;
	check_match(ls, TK_END, TK_FUNCTION, line);
	close_func(ls);
	pushclosure(ls, &new_fs, e);
}

static int explist1(LexState * ls, expdesc * v)
{
	int n = 1;
	expr(ls, v);
	while (testnext(ls, ',')) {
		luaK_exp2nextreg(ls->fs, v);
		expr(ls, v);
		n++;
	}
	return n;
}

static void funcargs(LexState * ls, expdesc * f)
{
	FuncState *fs = ls->fs;
	expdesc args;
	int base, nparams;
	int line = ls->linenumber;
	switch (ls->t.token) {
	case '(':{
			if (line != ls->lastline)
				luaX_syntaxerror(ls,
						 "ambiguous syntax (function call x new statement)");
			luaX_next(ls);
			if (ls->t.token == ')')
				args.k = VVOID;
			else {
				explist1(ls, &args);
				luaK_setmultret(fs, &args);
			}
			check_match(ls, ')', '(', line);
			break;
		}
	case '{':{
			constructor(ls, &args);
			break;
		}
	case TK_STRING:{
			codestring(ls, &args, ls->t.seminfo.ts);
			luaX_next(ls);
			break;
		}
	default:{
			luaX_syntaxerror(ls, "function arguments expected");
			return;
		}
	}
	base = f->u.s.info;
	if (hasmultret(args.k))
		nparams = (-1);
	else {
		if (args.k != VVOID)
			luaK_exp2nextreg(fs, &args);
		nparams = fs->freereg - (base + 1);
	}
	init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams + 1, 2));
	luaK_fixline(fs, line);
	fs->freereg = base + 1;
}

static void prefixexp(LexState * ls, expdesc * v)
{
	switch (ls->t.token) {
	case '(':{
			int line = ls->linenumber;
			luaX_next(ls);
			expr(ls, v);
			check_match(ls, ')', '(', line);
			luaK_dischargevars(ls->fs, v);
			return;
		}
	case TK_NAME:{
			singlevar(ls, v);
			return;
		}
	default:{
			luaX_syntaxerror(ls, "unexpected symbol");
			return;
		}
	}
}

static void primaryexp(LexState * ls, expdesc * v)
{
	FuncState *fs = ls->fs;
	prefixexp(ls, v);
	for (;;) {
		switch (ls->t.token) {
		case '.':{
				field(ls, v);
				break;
			}
		case '[':{
				expdesc key;
				luaK_exp2anyreg(fs, v);
				yindex(ls, &key);
				luaK_indexed(fs, v, &key);
				break;
			}
		case ':':{
				expdesc key;
				luaX_next(ls);
				checkname(ls, &key);
				luaK_self(fs, v, &key);
				funcargs(ls, v);
				break;
			}
		case '(':
		case TK_STRING:
		case '{':{
				luaK_exp2nextreg(fs, v);
				funcargs(ls, v);
				break;
			}
		default:
			return;
		}
	}
}

static void simpleexp(LexState * ls, expdesc * v)
{
	switch (ls->t.token) {
	case TK_NUMBER:{
			init_exp(v, VKNUM, 0);
			v->u.nval = ls->t.seminfo.r;
			break;
		}
	case TK_STRING:{
			codestring(ls, v, ls->t.seminfo.ts);
			break;
		}
	case TK_NIL:{
			init_exp(v, VNIL, 0);
			break;
		}
	case TK_TRUE:{
			init_exp(v, VTRUE, 0);
			break;
		}
	case TK_FALSE:{
			init_exp(v, VFALSE, 0);
			break;
		}
	case TK_DOTS:{
			FuncState *fs = ls->fs;
			check_condition(ls, fs->f->is_vararg,
					"cannot use " LUA_QL("...")
					" outside a vararg function");
			fs->f->is_vararg &= ~4;
			init_exp(v, VVARARG,
				 luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
			break;
		}
	case '{':{
			constructor(ls, v);
			return;
		}
	case TK_FUNCTION:{
			luaX_next(ls);
			body(ls, v, 0, ls->linenumber);
			return;
		}
	default:{
			primaryexp(ls, v);
			return;
		}
	}
	luaX_next(ls);
}

static UnOpr getunopr(int op)
{
	switch (op) {
	case TK_NOT:
		return OPR_NOT;
	case '-':
		return OPR_MINUS;
	case '#':
		return OPR_LEN;
	default:
		return OPR_NOUNOPR;
	}
}

static BinOpr getbinopr(int op)
{
	switch (op) {
	case '+':
		return OPR_ADD;
	case '-':
		return OPR_SUB;
	case '*':
		return OPR_MUL;
	case '/':
		return OPR_DIV;
	case '%':
		return OPR_MOD;
	case '^':
		return OPR_POW;
	case TK_CONCAT:
		return OPR_CONCAT;
	case TK_NE:
		return OPR_NE;
	case TK_EQ:
		return OPR_EQ;
	case '<':
		return OPR_LT;
	case TK_LE:
		return OPR_LE;
	case '>':
		return OPR_GT;
	case TK_GE:
		return OPR_GE;
	case TK_AND:
		return OPR_AND;
	case TK_OR:
		return OPR_OR;
	default:
		return OPR_NOBINOPR;
	}
}

static const struct {
	lu_byte left;
	lu_byte right;
} priority[] = {
	{6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7},
	{10, 9}, {5, 4},
	{3, 3}, {3, 3},
	{3, 3}, {3, 3}, {3, 3}, {3, 3},
	{2, 2}, {1, 1}
};

static BinOpr subexpr(LexState * ls, expdesc * v, unsigned int limit)
{
	BinOpr op;
	UnOpr uop;
	enterlevel(ls);
	uop = getunopr(ls->t.token);
	if (uop != OPR_NOUNOPR) {
		luaX_next(ls);
		subexpr(ls, v, 8);
		luaK_prefix(ls->fs, uop, v);
	} else
		simpleexp(ls, v);
	op = getbinopr(ls->t.token);
	while (op != OPR_NOBINOPR && priority[op].left > limit) {
		expdesc v2;
		BinOpr nextop;
		luaX_next(ls);
		luaK_infix(ls->fs, op, v);
		nextop = subexpr(ls, &v2, priority[op].right);
		luaK_posfix(ls->fs, op, v, &v2);
		op = nextop;
	}
	leavelevel(ls);
	return op;
}

static void expr(LexState * ls, expdesc * v)
{
	subexpr(ls, v, 0);
}

static int block_follow(int token)
{
	switch (token) {
	case TK_ELSE:
	case TK_ELSEIF:
	case TK_END:
	case TK_UNTIL:
	case TK_EOS:
		return 1;
	default:
		return 0;
	}
}

static void block(LexState * ls)
{
	FuncState *fs = ls->fs;
	BlockCnt bl;
	enterblock(fs, &bl, 0);
	chunk(ls);
	leaveblock(fs);
}

struct LHS_assign {
	struct LHS_assign *prev;
	expdesc v;
};
static void check_conflict(LexState * ls, struct LHS_assign *lh, expdesc * v)
{
	FuncState *fs = ls->fs;
	int extra = fs->freereg;
	int conflict = 0;
	for (; lh; lh = lh->prev) {
		if (lh->v.k == VINDEXED) {
			if (lh->v.u.s.info == v->u.s.info) {
				conflict = 1;
				lh->v.u.s.info = extra;
			}
			if (lh->v.u.s.aux == v->u.s.info) {
				conflict = 1;
				lh->v.u.s.aux = extra;
			}
		}
	}
	if (conflict) {
		luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0);
		luaK_reserveregs(fs, 1);
	}
}

static void assignment(LexState * ls, struct LHS_assign *lh, int nvars)
{
	expdesc e;
	check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,
			"syntax error");
	if (testnext(ls, ',')) {
		struct LHS_assign nv;
		nv.prev = lh;
		primaryexp(ls, &nv.v);
		if (nv.v.k == VLOCAL)
			check_conflict(ls, lh, &nv.v);
		luaY_checklimit(ls->fs, nvars, 200 - ls->L->nCcalls,
				"variables in assignment");
		assignment(ls, &nv, nvars + 1);
	} else {
		int nexps;
		checknext(ls, '=');
		nexps = explist1(ls, &e);
		if (nexps != nvars) {
			adjust_assign(ls, nvars, nexps, &e);
			if (nexps > nvars)
				ls->fs->freereg -= nexps - nvars;
		} else {
			luaK_setoneret(ls->fs, &e);
			luaK_storevar(ls->fs, &lh->v, &e);
			return;
		}
	}
	init_exp(&e, VNONRELOC, ls->fs->freereg - 1);
	luaK_storevar(ls->fs, &lh->v, &e);
}

static int cond(LexState * ls)
{
	expdesc v;
	expr(ls, &v);
	if (v.k == VNIL)
		v.k = VFALSE;
	luaK_goiftrue(ls->fs, &v);
	return v.f;
}

static void breakstat(LexState * ls)
{
	FuncState *fs = ls->fs;
	BlockCnt *bl = fs->bl;
	int upval = 0;
	while (bl && !bl->isbreakable) {
		upval |= bl->upval;
		bl = bl->previous;
	}
	if (!bl)
		luaX_syntaxerror(ls, "no loop to break");
	if (upval)
		luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
	luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
}

static void whilestat(LexState * ls, int line)
{
	FuncState *fs = ls->fs;
	int whileinit;
	int condexit;
	BlockCnt bl;
	luaX_next(ls);
	whileinit = luaK_getlabel(fs);
	condexit = cond(ls);
	enterblock(fs, &bl, 1);
	checknext(ls, TK_DO);
	block(ls);
	luaK_patchlist(fs, luaK_jump(fs), whileinit);
	check_match(ls, TK_END, TK_WHILE, line);
	leaveblock(fs);
	luaK_patchtohere(fs, condexit);
}

static void repeatstat(LexState * ls, int line)
{
	int condexit;
	FuncState *fs = ls->fs;
	int repeat_init = luaK_getlabel(fs);
	BlockCnt bl1, bl2;
	enterblock(fs, &bl1, 1);
	enterblock(fs, &bl2, 0);
	luaX_next(ls);
	chunk(ls);
	check_match(ls, TK_UNTIL, TK_REPEAT, line);
	condexit = cond(ls);
	if (!bl2.upval) {
		leaveblock(fs);
		luaK_patchlist(ls->fs, condexit, repeat_init);
	} else {
		breakstat(ls);
		luaK_patchtohere(ls->fs, condexit);
		leaveblock(fs);
		luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init);
	}
	leaveblock(fs);
}

static int exp1(LexState * ls)
{
	expdesc e;
	int k;
	expr(ls, &e);
	k = e.k;
	luaK_exp2nextreg(ls->fs, &e);
	return k;
}

static void forbody(LexState * ls, int base, int line, int nvars, int isnum)
{
	BlockCnt bl;
	FuncState *fs = ls->fs;
	int prep, endfor;
	adjustlocalvars(ls, 3);
	checknext(ls, TK_DO);
	prep =
	    isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, (-1)) : luaK_jump(fs);
	enterblock(fs, &bl, 0);
	adjustlocalvars(ls, nvars);
	luaK_reserveregs(fs, nvars);
	block(ls);
	leaveblock(fs);
	luaK_patchtohere(fs, prep);
	endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, (-1)) :
	    luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
	luaK_fixline(fs, line);
	luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
}

static void fornum(LexState * ls, TString * varname, int line)
{
	FuncState *fs = ls->fs;
	int base = fs->freereg;
	new_localvarliteral(ls, "(for index)", 0);
	new_localvarliteral(ls, "(for limit)", 1);
	new_localvarliteral(ls, "(for step)", 2);
	new_localvar(ls, varname, 3);
	checknext(ls, '=');
	exp1(ls);
	checknext(ls, ',');
	exp1(ls);
	if (testnext(ls, ','))
		exp1(ls);
	else {
		luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
		luaK_reserveregs(fs, 1);
	}
	forbody(ls, base, line, 1, 1);
}

static void forlist(LexState * ls, TString * indexname)
{
	FuncState *fs = ls->fs;
	expdesc e;
	int nvars = 0;
	int line;
	int base = fs->freereg;
	new_localvarliteral(ls, "(for generator)", nvars++);
	new_localvarliteral(ls, "(for state)", nvars++);
	new_localvarliteral(ls, "(for control)", nvars++);
	new_localvar(ls, indexname, nvars++);
	while (testnext(ls, ','))
		new_localvar(ls, str_checkname(ls), nvars++);
	checknext(ls, TK_IN);
	line = ls->linenumber;
	adjust_assign(ls, 3, explist1(ls, &e), &e);
	luaK_checkstack(fs, 3);
	forbody(ls, base, line, nvars - 3, 0);
}

static void forstat(LexState * ls, int line)
{
	FuncState *fs = ls->fs;
	TString *varname;
	BlockCnt bl;
	enterblock(fs, &bl, 1);
	luaX_next(ls);
	varname = str_checkname(ls);
	switch (ls->t.token) {
	case '=':
		fornum(ls, varname, line);
		break;
	case ',':
	case TK_IN:
		forlist(ls, varname);
		break;
	default:
		luaX_syntaxerror(ls,
				 LUA_QL("=") " or " LUA_QL("in") " expected");
	}
	check_match(ls, TK_END, TK_FOR, line);
	leaveblock(fs);
}

static int test_then_block(LexState * ls)
{
	int condexit;
	luaX_next(ls);
	condexit = cond(ls);
	checknext(ls, TK_THEN);
	block(ls);
	return condexit;
}

static void ifstat(LexState * ls, int line)
{
	FuncState *fs = ls->fs;
	int flist;
	int escapelist = (-1);
	flist = test_then_block(ls);
	while (ls->t.token == TK_ELSEIF) {
		luaK_concat(fs, &escapelist, luaK_jump(fs));
		luaK_patchtohere(fs, flist);
		flist = test_then_block(ls);
	}
	if (ls->t.token == TK_ELSE) {
		luaK_concat(fs, &escapelist, luaK_jump(fs));
		luaK_patchtohere(fs, flist);
		luaX_next(ls);
		block(ls);
	} else
		luaK_concat(fs, &escapelist, flist);
	luaK_patchtohere(fs, escapelist);
	check_match(ls, TK_END, TK_IF, line);
}

static void localfunc(LexState * ls)
{
	expdesc v, b;
	FuncState *fs = ls->fs;
	new_localvar(ls, str_checkname(ls), 0);
	init_exp(&v, VLOCAL, fs->freereg);
	luaK_reserveregs(fs, 1);
	adjustlocalvars(ls, 1);
	body(ls, &b, 0, ls->linenumber);
	luaK_storevar(fs, &v, &b);
	getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;
}

static void localstat(LexState * ls)
{
	int nvars = 0;
	int nexps;
	expdesc e;
	do {
		new_localvar(ls, str_checkname(ls), nvars++);
	} while (testnext(ls, ','));
	if (testnext(ls, '='))
		nexps = explist1(ls, &e);
	else {
		e.k = VVOID;
		nexps = 0;
	}
	adjust_assign(ls, nvars, nexps, &e);
	adjustlocalvars(ls, nvars);
}

static int funcname(LexState * ls, expdesc * v)
{
	int needself = 0;
	singlevar(ls, v);
	while (ls->t.token == '.')
		field(ls, v);
	if (ls->t.token == ':') {
		needself = 1;
		field(ls, v);
	}
	return needself;
}

static void funcstat(LexState * ls, int line)
{
	int needself;
	expdesc v, b;
	luaX_next(ls);
	needself = funcname(ls, &v);
	body(ls, &b, needself, line);
	luaK_storevar(ls->fs, &v, &b);
	luaK_fixline(ls->fs, line);
}

static void exprstat(LexState * ls)
{
	FuncState *fs = ls->fs;
	struct LHS_assign v;
	primaryexp(ls, &v.v);
	if (v.v.k == VCALL)
		SETARG_C(getcode(fs, &v.v), 1);
	else {
		v.prev = NULL;
		assignment(ls, &v, 1);
	}
}

static void retstat(LexState * ls)
{
	FuncState *fs = ls->fs;
	expdesc e;
	int first, nret;
	luaX_next(ls);
	if (block_follow(ls->t.token) || ls->t.token == ';')
		first = nret = 0;
	else {
		nret = explist1(ls, &e);
		if (hasmultret(e.k)) {
			luaK_setmultret(fs, &e);
			if (e.k == VCALL && nret == 1) {
				SET_OPCODE(getcode(fs, &e), OP_TAILCALL);
			}
			first = fs->nactvar;
			nret = (-1);
		} else {
			if (nret == 1)
				first = luaK_exp2anyreg(fs, &e);
			else {
				luaK_exp2nextreg(fs, &e);
				first = fs->nactvar;
			}
		}
	}
	luaK_ret(fs, first, nret);
}

static int statement(LexState * ls)
{
	int line = ls->linenumber;
	switch (ls->t.token) {
	case TK_IF:{
			ifstat(ls, line);
			return 0;
		}
	case TK_WHILE:{
			whilestat(ls, line);
			return 0;
		}
	case TK_DO:{
			luaX_next(ls);
			block(ls);
			check_match(ls, TK_END, TK_DO, line);
			return 0;
		}
	case TK_FOR:{
			forstat(ls, line);
			return 0;
		}
	case TK_REPEAT:{
			repeatstat(ls, line);
			return 0;
		}
	case TK_FUNCTION:{
			funcstat(ls, line);
			return 0;
		}
	case TK_LOCAL:{
			luaX_next(ls);
			if (testnext(ls, TK_FUNCTION))
				localfunc(ls);
			else
				localstat(ls);
			return 0;
		}
	case TK_RETURN:{
			retstat(ls);
			return 1;
		}
	case TK_BREAK:{
			luaX_next(ls);
			breakstat(ls);
			return 1;
		}
	default:{
			exprstat(ls);
			return 0;
		}
	}
}

static void chunk(LexState * ls)
{
	int islast = 0;
	enterlevel(ls);
	while (!islast && !block_follow(ls->t.token)) {
		islast = statement(ls);
		testnext(ls, ';');
		ls->fs->freereg = ls->fs->nactvar;
	}
	leavelevel(ls);
}

static const TValue *luaV_tonumber(const TValue * obj, TValue * n)
{
	lua_Number num;
	if (ttisnumber(obj))
		return obj;
	if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
		setnvalue(n, num);
		return n;
	} else
		return NULL;
}

static int luaV_tostring(lua_State * L, StkId obj)
{
	if (!ttisnumber(obj))
		return 0;
	else {
		char s[32];
		lua_Number n = nvalue(obj);
		lua_number2str(s, n);
		setsvalue(L, obj, luaS_new(L, s));
		return 1;
	}
}

static void callTMres(lua_State * L, StkId res, const TValue * f,
		      const TValue * p1, const TValue * p2)
{
	ptrdiff_t result = savestack(L, res);
	setobj(L, L->top, f);
	setobj(L, L->top + 1, p1);
	setobj(L, L->top + 2, p2);
	luaD_checkstack(L, 3);
	L->top += 3;
	luaD_call(L, L->top - 3, 1);
	res = restorestack(L, result);
	L->top--;
	setobj(L, res, L->top);
}

static void callTM(lua_State * L, const TValue * f, const TValue * p1,
		   const TValue * p2, const TValue * p3)
{
	setobj(L, L->top, f);
	setobj(L, L->top + 1, p1);
	setobj(L, L->top + 2, p2);
	setobj(L, L->top + 3, p3);
	luaD_checkstack(L, 4);
	L->top += 4;
	luaD_call(L, L->top - 4, 0);
}

static void luaV_gettable(lua_State * L, const TValue * t, TValue * key,
			  StkId val)
{
	int loop;
	for (loop = 0; loop < 100; loop++) {
		const TValue *tm;
		if (ttistable(t)) {
			Table *h = hvalue(t);
			const TValue *res = luaH_get(h, key);
			if (!ttisnil(res) ||
			    (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) {
				setobj(L, val, res);
				return;
			}
		} else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
			luaG_typeerror(L, t, "index");
		if (ttisfunction(tm)) {
			callTMres(L, val, tm, t, key);
			return;
		}
		t = tm;
	}
	luaG_runerror(L, "loop in gettable");
}

static void luaV_settable(lua_State * L, const TValue * t, TValue * key,
			  StkId val)
{
	int loop;
	TValue temp;
	for (loop = 0; loop < 100; loop++) {
		const TValue *tm;
		if (ttistable(t)) {
			Table *h = hvalue(t);
			TValue *oldval = luaH_set(L, h, key);
			if (!ttisnil(oldval) ||
			    (tm =
			     fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) {
				setobj(L, oldval, val);
				h->flags = 0;
				luaC_barriert(L, h, val);
				return;
			}
		} else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
			luaG_typeerror(L, t, "index");
		if (ttisfunction(tm)) {
			callTM(L, tm, t, key, val);
			return;
		}
		setobj(L, &temp, tm);
		t = &temp;
	}
	luaG_runerror(L, "loop in settable");
}

static int call_binTM(lua_State * L, const TValue * p1, const TValue * p2,
		      StkId res, TMS event)
{
	const TValue *tm = luaT_gettmbyobj(L, p1, event);
	if (ttisnil(tm))
		tm = luaT_gettmbyobj(L, p2, event);
	if (ttisnil(tm))
		return 0;
	callTMres(L, res, tm, p1, p2);
	return 1;
}

static const TValue *get_compTM(lua_State * L, Table * mt1, Table * mt2,
				TMS event)
{
	const TValue *tm1 = fasttm(L, mt1, event);
	const TValue *tm2;
	if (tm1 == NULL)
		return NULL;
	if (mt1 == mt2)
		return tm1;
	tm2 = fasttm(L, mt2, event);
	if (tm2 == NULL)
		return NULL;
	if (luaO_rawequalObj(tm1, tm2))
		return tm1;
	return NULL;
}

static int call_orderTM(lua_State * L, const TValue * p1, const TValue * p2,
			TMS event)
{
	const TValue *tm1 = luaT_gettmbyobj(L, p1, event);
	const TValue *tm2;
	if (ttisnil(tm1))
		return -1;
	tm2 = luaT_gettmbyobj(L, p2, event);
	if (!luaO_rawequalObj(tm1, tm2))
		return -1;
	callTMres(L, L->top, tm1, p1, p2);
	return !l_isfalse(L->top);
}

static int l_strcmp(const TString * ls, const TString * rs)
{
	const char *l = getstr(ls);
	size_t ll = ls->tsv.len;
	const char *r = getstr(rs);
	size_t lr = rs->tsv.len;
	for (;;) {
		int temp = strcoll(l, r);
		if (temp != 0)
			return temp;
		else {
			size_t len = strlen(l);
			if (len == lr)
				return (len == ll) ? 0 : 1;
			else if (len == ll)
				return -1;
			len++;
			l += len;
			ll -= len;
			r += len;
			lr -= len;
		}
	}
}

static int luaV_lessthan(lua_State * L, const TValue * l, const TValue * r)
{
	int res;
	if (ttype(l) != ttype(r))
		return luaG_ordererror(L, l, r);
	else if (ttisnumber(l))
		return luai_numlt(nvalue(l), nvalue(r));
	else if (ttisstring(l))
		return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
	else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
		return res;
	return luaG_ordererror(L, l, r);
}

static int lessequal(lua_State * L, const TValue * l, const TValue * r)
{
	int res;
	if (ttype(l) != ttype(r))
		return luaG_ordererror(L, l, r);
	else if (ttisnumber(l))
		return luai_numle(nvalue(l), nvalue(r));
	else if (ttisstring(l))
		return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
	else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)
		return res;
	else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)
		return !res;
	return luaG_ordererror(L, l, r);
}

static int luaV_equalval(lua_State * L, const TValue * t1, const TValue * t2)
{
	const TValue *tm;
	switch (ttype(t1)) {
	case 0:
		return 1;
	case 3:
		return luai_numeq(nvalue(t1), nvalue(t2));
	case 1:
		return bvalue(t1) == bvalue(t2);
	case 2:
		return pvalue(t1) == pvalue(t2);
	case 7:{
			if (uvalue(t1) == uvalue(t2))
				return 1;
			tm = get_compTM(L, uvalue(t1)->metatable,
					uvalue(t2)->metatable, TM_EQ);
			break;
		}
	case 5:{
			if (hvalue(t1) == hvalue(t2))
				return 1;
			tm = get_compTM(L, hvalue(t1)->metatable,
					hvalue(t2)->metatable, TM_EQ);
			break;
		}
	default:
		return gcvalue(t1) == gcvalue(t2);
	}
	if (tm == NULL)
		return 0;
	callTMres(L, L->top, tm, t1, t2);
	return !l_isfalse(L->top);
}

static void luaV_concat(lua_State * L, int total, int last)
{
	do {
		StkId top = L->base + last + 1;
		int n = 2;
		if (!(ttisstring(top - 2) || ttisnumber(top - 2))
		    || !tostring(L, top - 1)) {
			if (!call_binTM
			    (L, top - 2, top - 1, top - 2, TM_CONCAT))
				luaG_concaterror(L, top - 2, top - 1);
		} else if (tsvalue(top - 1)->len == 0)
			(void)tostring(L, top - 2);
		else {
			size_t tl = tsvalue(top - 1)->len;
			char *buffer;
			int i;
			for (n = 1; n < total && tostring(L, top - n - 1); n++) {
				size_t l = tsvalue(top - n - 1)->len;
				if (l >= ((size_t)(~(size_t)0) - 2) - tl)
					luaG_runerror(L,
						      "string length overflow");
				tl += l;
			}
			buffer = luaZ_openspace(L, &G(L)->buff, tl);
			tl = 0;
			for (i = n; i > 0; i--) {
				size_t l = tsvalue(top - i)->len;
				memcpy(buffer + tl, svalue(top - i), l);
				tl += l;
			}
			setsvalue(L, top - n, luaS_newlstr(L, buffer, tl));
		}
		total -= n - 1;
		last -= n - 1;
	} while (total > 1);
}

static void Arith(lua_State * L, StkId ra, const TValue * rb,
		  const TValue * rc, TMS op)
{
	TValue tempb, tempc;
	const TValue *b, *c;
	if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
	    (c = luaV_tonumber(rc, &tempc)) != NULL) {
		lua_Number nb = nvalue(b), nc = nvalue(c);
		switch (op) {
		case TM_ADD:
			setnvalue(ra, luai_numadd(nb, nc));
			break;
		case TM_SUB:
			setnvalue(ra, luai_numsub(nb, nc));
			break;
		case TM_MUL:
			setnvalue(ra, luai_nummul(nb, nc));
			break;
		case TM_DIV:
			setnvalue(ra, luai_numdiv(nb, nc));
			break;
		case TM_MOD:
			setnvalue(ra, luai_nummod(nb, nc));
			break;
		case TM_POW:
			setnvalue(ra, luai_numpow(nb, nc));
			break;
		case TM_UNM:
			setnvalue(ra, luai_numunm(nb));
			break;
		default:
			break;
		}
	} else if (!call_binTM(L, rb, rc, ra, op))
		luaG_aritherror(L, rb, rc);
}

#define runtime_check(L,c){if(!(c))break;}
#define RA(i)(base+GETARG_A(i))
#define RB(i)check_exp(getBMode(GET_OPCODE(i))==OpArgR,base+GETARG_B(i))
#define RKB(i)check_exp(getBMode(GET_OPCODE(i))==OpArgK,ISK(GETARG_B(i))?k+INDEXK(GETARG_B(i)):base+GETARG_B(i))
#define RKC(i)check_exp(getCMode(GET_OPCODE(i))==OpArgK,ISK(GETARG_C(i))?k+INDEXK(GETARG_C(i)):base+GETARG_C(i))
#define KBx(i)check_exp(getBMode(GET_OPCODE(i))==OpArgK,k+GETARG_Bx(i))
#define dojump(L,pc,i){(pc)+=(i);}
#define Protect(x){L->savedpc=pc;{x;};base=L->base;}
#define arith_op(op,tm){TValue*rb=RKB(i);TValue*rc=RKC(i);if(ttisnumber(rb)&&ttisnumber(rc)){lua_Number nb=nvalue(rb),nc=nvalue(rc);setnvalue(ra,op(nb,nc));}else Protect(Arith(L,ra,rb,rc,tm));}
static void luaV_execute(lua_State * L, int nexeccalls)
{
	LClosure *cl;
	StkId base;
	TValue *k;
	const Instruction *pc;
 reentry:
	pc = L->savedpc;
	cl = &clvalue(L->ci->func)->l;
	base = L->base;
	k = cl->p->k;
	for (;;) {
		const Instruction i = *pc++;
		StkId ra;
		ra = RA(i);
		switch (GET_OPCODE(i)) {
		case OP_MOVE:{
				setobj(L, ra, RB(i));
				continue;
			}
		case OP_LOADK:{
				setobj(L, ra, KBx(i));
				continue;
			}
		case OP_LOADBOOL:{
				setbvalue(ra, GETARG_B(i));
				if (GETARG_C(i))
					pc++;
				continue;
			}
		case OP_LOADNIL:{
				TValue *rb = RB(i);
				do {
					setnilvalue(rb--);
				} while (rb >= ra);
				continue;
			}
		case OP_GETUPVAL:{
				int b = GETARG_B(i);
				setobj(L, ra, cl->upvals[b]->v);
				continue;
			}
		case OP_GETGLOBAL:{
				TValue g;
				TValue *rb = KBx(i);
				sethvalue(L, &g, cl->env);
				Protect(luaV_gettable(L, &g, rb, ra));
				continue;
			}
		case OP_GETTABLE:{
				Protect(luaV_gettable(L, RB(i), RKC(i), ra));
				continue;
			}
		case OP_SETGLOBAL:{
				TValue g;
				sethvalue(L, &g, cl->env);
				Protect(luaV_settable(L, &g, KBx(i), ra));
				continue;
			}
		case OP_SETUPVAL:{
				UpVal *uv = cl->upvals[GETARG_B(i)];
				setobj(L, uv->v, ra);
				luaC_barrier(L, uv, ra);
				continue;
			}
		case OP_SETTABLE:{
				Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
				continue;
			}
		case OP_NEWTABLE:{
				int b = GETARG_B(i);
				int c = GETARG_C(i);
				sethvalue(L, ra,
					  luaH_new(L, luaO_fb2int(b),
						   luaO_fb2int(c)));
				Protect(luaC_checkGC(L));
				continue;
			}
		case OP_SELF:{
				StkId rb = RB(i);
				setobj(L, ra + 1, rb);
				Protect(luaV_gettable(L, rb, RKC(i), ra));
				continue;
			}
		case OP_ADD:{
				arith_op(luai_numadd, TM_ADD);
				continue;
			}
		case OP_SUB:{
				arith_op(luai_numsub, TM_SUB);
				continue;
			}
		case OP_MUL:{
				arith_op(luai_nummul, TM_MUL);
				continue;
			}
		case OP_DIV:{
				arith_op(luai_numdiv, TM_DIV);
				continue;
			}
		case OP_MOD:{
				arith_op(luai_nummod, TM_MOD);
				continue;
			}
		case OP_POW:{
				arith_op(luai_numpow, TM_POW);
				continue;
			}
		case OP_UNM:{
				TValue *rb = RB(i);
				if (ttisnumber(rb)) {
					lua_Number nb = nvalue(rb);
					setnvalue(ra, luai_numunm(nb));
				} else {
					Protect(Arith(L, ra, rb, rb, TM_UNM));
				}
				continue;
			}
		case OP_NOT:{
				int res = l_isfalse(RB(i));
				setbvalue(ra, res);
				continue;
			}
		case OP_LEN:{
				const TValue *rb = RB(i);
				switch (ttype(rb)) {
				case 5:{
						setnvalue(ra,
							  cast_num(luaH_getn
								   (hvalue
								    (rb))));
						break;
					}
				case 4:{
						setnvalue(ra,
							  cast_num(tsvalue(rb)->
								   len));
						break;
					}
				default:{
						Protect(if
							(!call_binTM
							 (L, rb,
							  (&luaO_nilobject_),
							  ra, TM_LEN))
							luaG_typeerror(L, rb,
								       "get length of");)
							}
							}
							continue;
					}
				case OP_CONCAT:{
						int b = GETARG_B(i);
						int c = GETARG_C(i);
						Protect(luaV_concat
							(L, c - b + 1, c);
							luaC_checkGC(L));
						setobj(L, RA(i), base + b);
						continue;
					}
				case OP_JMP:{
						dojump(L, pc, GETARG_sBx(i));
						continue;
					}
				case OP_EQ:{
						TValue *rb = RKB(i);
						TValue *rc = RKC(i);
						Protect(if
							(equalobj(L, rb, rc) ==
							 GETARG_A(i))
							dojump(L, pc,
							       GETARG_sBx
							       (*pc));)
							pc++;
						continue;
					}
				case OP_LT:{
						Protect(if
							(luaV_lessthan
							 (L, RKB(i),
							  RKC(i)) ==
							 GETARG_A(i))
							dojump(L, pc,
							       GETARG_sBx
							       (*pc));)
							pc++;
						continue;
					}
				case OP_LE:{
						Protect(if
							(lessequal
							 (L, RKB(i),
							  RKC(i)) ==
							 GETARG_A(i))
							dojump(L, pc,
							       GETARG_sBx
							       (*pc));)
							pc++;
						continue;
					}
				case OP_TEST:{
						if (l_isfalse(ra) !=
						    GETARG_C(i))
							dojump(L, pc,
							       GETARG_sBx(*pc));
						pc++;
						continue;
					}
				case OP_TESTSET:{
						TValue *rb = RB(i);
						if (l_isfalse(rb) !=
						    GETARG_C(i)) {
							setobj(L, ra, rb);
							dojump(L, pc,
							       GETARG_sBx(*pc));
						}
						pc++;
						continue;
					}
				case OP_CALL:{
						int b = GETARG_B(i);
						int nresults = GETARG_C(i) - 1;
						if (b != 0)
							L->top = ra + b;
						L->savedpc = pc;
						switch (luaD_precall
							(L, ra, nresults)) {
						case 0:{
								nexeccalls++;
								goto reentry;
							}
						case 1:{
								if (nresults >=
								    0)
									L->top =
									    L->
									    ci->
									    top;
								base = L->base;
								continue;
							}
						default:{
								return;
							}
						}
					}
				case OP_TAILCALL:{
						int b = GETARG_B(i);
						if (b != 0)
							L->top = ra + b;
						L->savedpc = pc;
						switch (luaD_precall
							(L, ra, (-1))) {
						case 0:{
								CallInfo *ci =
								    L->ci - 1;
								int aux;
								StkId func =
								    ci->func;
								StkId pfunc =
								    (ci +
								     1)->func;
								if (L->
								    openupval)
									luaF_close
									    (L,
									     ci->
									     base);
								L->base =
								    ci->base =
								    ci->func +
								    ((ci +
								      1)->base -
								     pfunc);
								for (aux = 0;
								     pfunc +
								     aux <
								     L->top;
								     aux++)
									setobj
									    (L,
									     func
									     +
									     aux,
									     pfunc
									     +
									     aux);
								ci->top =
								    L->top =
								    func + aux;
								ci->savedpc =
								    L->savedpc;
								ci->tailcalls++;
								L->ci--;
								goto reentry;
							}
						case 1:{
								base = L->base;
								continue;
							}
						default:{
								return;
							}
						}
					}
				case OP_RETURN:{
						int b = GETARG_B(i);
						if (b != 0)
							L->top = ra + b - 1;
						if (L->openupval)
							luaF_close(L, base);
						L->savedpc = pc;
						b = luaD_poscall(L, ra);
						if (--nexeccalls == 0)
							return;
						else {
							if (b)
								L->top =
								    L->ci->top;
							goto reentry;
						}
					}
				case OP_FORLOOP:{
						lua_Number step =
						    nvalue(ra + 2);
						lua_Number idx =
						    luai_numadd(nvalue(ra),
								step);
						lua_Number limit =
						    nvalue(ra + 1);
						if (luai_numlt(0, step) ?
						    luai_numle(idx, limit)
						    : luai_numle(limit, idx)) {
							dojump(L, pc,
							       GETARG_sBx(i));
							setnvalue(ra, idx);
							setnvalue(ra + 3, idx);
						}
						continue;
					}
				case OP_FORPREP:{
						const TValue *init = ra;
						const TValue *plimit = ra + 1;
						const TValue *pstep = ra + 2;
						L->savedpc = pc;
						if (!tonumber(init, ra))
							luaG_runerror(L,
								      LUA_QL
								      ("for")
								      " initial value must be a number");
						else if (!tonumber
							 (plimit, ra + 1))
							luaG_runerror(L,
								      LUA_QL
								      ("for")
								      " limit must be a number");
						else if (!tonumber
							 (pstep, ra + 2))
							luaG_runerror(L,
								      LUA_QL
								      ("for")
								      " step must be a number");
						setnvalue(ra,
							  luai_numsub(nvalue
								      (ra),
								      nvalue
								      (pstep)));
						dojump(L, pc, GETARG_sBx(i));
						continue;
					}
				case OP_TFORLOOP:{
						StkId cb = ra + 3;
						setobj(L, cb + 2, ra + 2);
						setobj(L, cb + 1, ra + 1);
						setobj(L, cb, ra);
						L->top = cb + 3;
						Protect(luaD_call
							(L, cb, GETARG_C(i)));
						L->top = L->ci->top;
						cb = RA(i) + 3;
						if (!ttisnil(cb)) {
							setobj(L, cb - 1, cb);
							dojump(L, pc,
							       GETARG_sBx(*pc));
						}
						pc++;
						continue;
					}
				case OP_SETLIST:{
						int n = GETARG_B(i);
						int c = GETARG_C(i);
						int last;
						Table *h;
						if (n == 0) {
							n = cast_int(L->top -
								     ra) - 1;
							L->top = L->ci->top;
						}
						if (c == 0)
							c = cast_int(*pc++);
						runtime_check(L, ttistable(ra));
						h = hvalue(ra);
						last = ((c - 1) * 50) + n;
						if (last > h->sizearray)
							luaH_resizearray(L, h,
									 last);
						for (; n > 0; n--) {
							TValue *val = ra + n;
							setobj(L,
							       luaH_setnum(L, h,
									   last--),
							       val);
							luaC_barriert(L, h,
								      val);
						}
						continue;
					}
				case OP_CLOSE:{
						luaF_close(L, ra);
						continue;
					}
				case OP_CLOSURE:{
						Proto *p;
						Closure *ncl;
						int nup, j;
						p = cl->p->p[GETARG_Bx(i)];
						nup = p->nups;
						ncl =
						    luaF_newLclosure(L, nup,
								     cl->env);
						ncl->l.p = p;
						for (j = 0; j < nup; j++, pc++) {
							if (GET_OPCODE(*pc) ==
							    OP_GETUPVAL)
								ncl->l.
								    upvals[j] =
								    cl->
								    upvals
								    [GETARG_B
								     (*pc)];
							else {
								ncl->l.
								    upvals[j] =
								    luaF_findupval
								    (L,
								     base +
								     GETARG_B
								     (*pc));
							}
						}
						setclvalue(L, ra, ncl);
						Protect(luaC_checkGC(L));
						continue;
					}
				case OP_VARARG:{
						int b = GETARG_B(i) - 1;
						int j;
						CallInfo *ci = L->ci;
						int n =
						    cast_int(ci->base -
							     ci->func) -
						    cl->p->numparams - 1;
						if (b == (-1)) {
							Protect(luaD_checkstack
								(L, n));
							ra = RA(i);
							b = n;
							L->top = ra + n;
						}
						for (j = 0; j < b; j++) {
							if (j < n) {
								setobj(L,
								       ra + j,
								       ci->
								       base -
								       n + j);
							} else {
								setnilvalue(ra +
									    j);
							}
						}
						continue;
					}
				}
			}
		}
#define api_checknelems(L,n)luai_apicheck(L,(n)<=(L->top-L->base))
#define api_checkvalidindex(L,i)luai_apicheck(L,(i)!=(&luaO_nilobject_))
#define api_incr_top(L){luai_apicheck(L,L->top<L->ci->top);L->top++;}
		static TValue *index2adr(lua_State * L, int idx) {
			if (idx > 0) {
				TValue *o = L->base + (idx - 1);
				luai_apicheck(L, idx <= L->ci->top - L->base);
				if (o >= L->top)
					return cast(TValue *,
						    (&luaO_nilobject_));
				else
					return o;
			} else if (idx > (-10000)) {
				luai_apicheck(L, idx != 0
					      && -idx <= L->top - L->base);
				return L->top + idx;
			} else
				switch (idx) {
				case (-10000):
					return registry(L);
				case (-10001):{
						Closure *func = curr_func(L);
						sethvalue(L, &L->env,
							  func->c.env);
						return &L->env;
					}
				case (-10002):
					return gt(L);
				default:{
						Closure *func = curr_func(L);
						idx = (-10002) - idx;
						return (idx <=
							func->c.nupvalues)
						    ? &func->c.upvalue[idx - 1]
						    : cast(TValue *,
							   (&luaO_nilobject_));
					}
				}
		}
		static Table *getcurrenv(lua_State * L) {
			if (L->ci == L->base_ci)
				return hvalue(gt(L));
			else {
				Closure *func = curr_func(L);
				return func->c.env;
			}
		}
		static int lua_checkstack(lua_State * L, int size) {
			int res = 1;
			if (size > 8000 || (L->top - L->base + size) > 8000)
				res = 0;
			else if (size > 0) {
				luaD_checkstack(L, size);
				if (L->ci->top < L->top + size)
					L->ci->top = L->top + size;
			}
			return res;
		}
		static lua_CFunction lua_atpanic(lua_State * L,
						 lua_CFunction panicf) {
			lua_CFunction old;
			old = G(L)->panic;
			G(L)->panic = panicf;
			return old;
		}
		static int lua_gettop(lua_State * L) {
			return cast_int(L->top - L->base);
		}
		static void lua_settop(lua_State * L, int idx) {
			if (idx >= 0) {
				luai_apicheck(L,
					      idx <= L->stack_last - L->base);
				while (L->top < L->base + idx)
					setnilvalue(L->top++);
				L->top = L->base + idx;
			} else {
				luai_apicheck(L,
					      -(idx + 1) <= (L->top - L->base));
				L->top += idx + 1;
			}
		}
		static void lua_remove(lua_State * L, int idx) {
			StkId p;
			p = index2adr(L, idx);
			api_checkvalidindex(L, p);
			while (++p < L->top)
				setobj(L, p - 1, p);
			L->top--;
		}
		static void lua_insert(lua_State * L, int idx) {
			StkId p;
			StkId q;
			p = index2adr(L, idx);
			api_checkvalidindex(L, p);
			for (q = L->top; q > p; q--)
				setobj(L, q, q - 1);
			setobj(L, p, L->top);
		}
		static void lua_replace(lua_State * L, int idx) {
			StkId o;
			if (idx == (-10001) && L->ci == L->base_ci)
				luaG_runerror(L, "no calling environment");
			api_checknelems(L, 1);
			o = index2adr(L, idx);
			api_checkvalidindex(L, o);
			if (idx == (-10001)) {
				Closure *func = curr_func(L);
				luai_apicheck(L, ttistable(L->top - 1));
				func->c.env = hvalue(L->top - 1);
				luaC_barrier(L, func, L->top - 1);
			} else {
				setobj(L, o, L->top - 1);
				if (idx < (-10002))
					luaC_barrier(L, curr_func(L),
						     L->top - 1);
			}
			L->top--;
		}
		static void lua_pushvalue(lua_State * L, int idx) {
			setobj(L, L->top, index2adr(L, idx));
			api_incr_top(L);
		}
		static int lua_type(lua_State * L, int idx) {
			StkId o = index2adr(L, idx);
			return (o == (&luaO_nilobject_)) ? (-1) : ttype(o);
		}
		static const char *lua_typename(lua_State * L, int t) {
			UNUSED(L);
			return (t == (-1)) ? "no value" : luaT_typenames[t];
		}
		static int lua_iscfunction(lua_State * L, int idx) {
			StkId o = index2adr(L, idx);
			return iscfunction(o);
		}
		static int lua_isnumber(lua_State * L, int idx) {
			TValue n;
			const TValue *o = index2adr(L, idx);
			return tonumber(o, &n);
		}
		static int lua_isstring(lua_State * L, int idx) {
			int t = lua_type(L, idx);
			return (t == 4 || t == 3);
		}
		static int lua_rawequal(lua_State * L, int index1, int index2) {
			StkId o1 = index2adr(L, index1);
			StkId o2 = index2adr(L, index2);
			return (o1 == (&luaO_nilobject_)
				|| o2 ==
				(&luaO_nilobject_)) ? 0 : luaO_rawequalObj(o1,
									   o2);
		}
		static int lua_lessthan(lua_State * L, int index1, int index2) {
			StkId o1, o2;
			int i;
			o1 = index2adr(L, index1);
			o2 = index2adr(L, index2);
			i = (o1 == (&luaO_nilobject_)
			     || o2 == (&luaO_nilobject_)) ? 0 : luaV_lessthan(L,
									      o1,
									      o2);
			return i;
		}
		static lua_Number lua_tonumber(lua_State * L, int idx) {
			TValue n;
			const TValue *o = index2adr(L, idx);
			if (tonumber(o, &n))
				return nvalue(o);
			else
				return 0;
		}
		static lua_Integer lua_tointeger(lua_State * L, int idx) {
			TValue n;
			const TValue *o = index2adr(L, idx);
			if (tonumber(o, &n)) {
				lua_Integer res;
				lua_Number num = nvalue(o);
				lua_number2integer(res, num);
				return res;
			} else
				return 0;
		}
		static int lua_toboolean(lua_State * L, int idx) {
			const TValue *o = index2adr(L, idx);
			return !l_isfalse(o);
		}
		static const char *lua_tolstring(lua_State * L, int idx,
						 size_t *len) {
			StkId o = index2adr(L, idx);
			if (!ttisstring(o)) {
				if (!luaV_tostring(L, o)) {
					if (len != NULL)
						*len = 0;
					return NULL;
				}
				luaC_checkGC(L);
				o = index2adr(L, idx);
			}
			if (len != NULL)
				*len = tsvalue(o)->len;
			return svalue(o);
		}
		static size_t lua_objlen(lua_State * L, int idx) {
			StkId o = index2adr(L, idx);
			switch (ttype(o)) {
			case 4:
				return tsvalue(o)->len;
			case 7:
				return uvalue(o)->len;
			case 5:
				return luaH_getn(hvalue(o));
			case 3:{
					size_t l;
					l = (luaV_tostring(L, o) ? tsvalue(o)->
					     len : 0);
					return l;
				}
			default:
				return 0;
			}
		}
		static lua_CFunction lua_tocfunction(lua_State * L, int idx) {
			StkId o = index2adr(L, idx);
			return (!iscfunction(o)) ? NULL : clvalue(o)->c.f;
		}
		static void *lua_touserdata(lua_State * L, int idx) {
			StkId o = index2adr(L, idx);
			switch (ttype(o)) {
			case 7:
				return (rawuvalue(o) + 1);
			case 2:
				return pvalue(o);
			default:
				return NULL;
			}
		}
		static void lua_pushnil(lua_State * L) {
			setnilvalue(L->top);
			api_incr_top(L);
		}
		static void lua_pushnumber(lua_State * L, lua_Number n) {
			setnvalue(L->top, n);
			api_incr_top(L);
		}
		static void lua_pushinteger(lua_State * L, lua_Integer n) {
			setnvalue(L->top, cast_num(n));
			api_incr_top(L);
		}
		static void lua_pushlstring(lua_State * L, const char *s,
					    size_t len) {
			luaC_checkGC(L);
			setsvalue(L, L->top, luaS_newlstr(L, s, len));
			api_incr_top(L);
		}
		static void lua_pushstring(lua_State * L, const char *s) {
			if (s == NULL)
				lua_pushnil(L);
			else
				lua_pushlstring(L, s, strlen(s));
		}
		static const char *lua_pushvfstring(lua_State * L,
						    const char *fmt,
						    va_list argp) {
			const char *ret;
			luaC_checkGC(L);
			ret = luaO_pushvfstring(L, fmt, argp);
			return ret;
		}
		static const char *lua_pushfstring(lua_State * L,
						   const char *fmt, ...) {
			const char *ret;
			va_list argp;
			luaC_checkGC(L);
			va_start(argp, fmt);
			ret = luaO_pushvfstring(L, fmt, argp);
			va_end(argp);
			return ret;
		}
		static void lua_pushcclosure(lua_State * L, lua_CFunction fn,
					     int n) {
			Closure *cl;
			luaC_checkGC(L);
			api_checknelems(L, n);
			cl = luaF_newCclosure(L, n, getcurrenv(L));
			cl->c.f = fn;
			L->top -= n;
			while (n--)
				setobj(L, &cl->c.upvalue[n], L->top + n);
			setclvalue(L, L->top, cl);
			api_incr_top(L);
		}
		static void lua_pushboolean(lua_State * L, int b) {
			setbvalue(L->top, (b != 0));
			api_incr_top(L);
		}
		static int lua_pushthread(lua_State * L) {
			setthvalue(L, L->top, L);
			api_incr_top(L);
			return (G(L)->mainthread == L);
		}
		static void lua_gettable(lua_State * L, int idx) {
			StkId t;
			t = index2adr(L, idx);
			api_checkvalidindex(L, t);
			luaV_gettable(L, t, L->top - 1, L->top - 1);
		}
		static void lua_getfield(lua_State * L, int idx, const char *k) {
			StkId t;
			TValue key;
			t = index2adr(L, idx);
			api_checkvalidindex(L, t);
			setsvalue(L, &key, luaS_new(L, k));
			luaV_gettable(L, t, &key, L->top);
			api_incr_top(L);
		}
		static void lua_rawget(lua_State * L, int idx) {
			StkId t;
			t = index2adr(L, idx);
			luai_apicheck(L, ttistable(t));
			setobj(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
		}
		static void lua_rawgeti(lua_State * L, int idx, int n) {
			StkId o;
			o = index2adr(L, idx);
			luai_apicheck(L, ttistable(o));
			setobj(L, L->top, luaH_getnum(hvalue(o), n));
			api_incr_top(L);
		}
		static void lua_createtable(lua_State * L, int narray, int nrec) {
			luaC_checkGC(L);
			sethvalue(L, L->top, luaH_new(L, narray, nrec));
			api_incr_top(L);
		}
		static int lua_getmetatable(lua_State * L, int objindex) {
			const TValue *obj;
			Table *mt = NULL;
			int res;
			obj = index2adr(L, objindex);
			switch (ttype(obj)) {
			case 5:
				mt = hvalue(obj)->metatable;
				break;
			case 7:
				mt = uvalue(obj)->metatable;
				break;
			default:
				mt = G(L)->mt[ttype(obj)];
				break;
			}
			if (mt == NULL)
				res = 0;
			else {
				sethvalue(L, L->top, mt);
				api_incr_top(L);
				res = 1;
			}
			return res;
		}
		static void lua_getfenv(lua_State * L, int idx) {
			StkId o;
			o = index2adr(L, idx);
			api_checkvalidindex(L, o);
			switch (ttype(o)) {
			case 6:
				sethvalue(L, L->top, clvalue(o)->c.env);
				break;
			case 7:
				sethvalue(L, L->top, uvalue(o)->env);
				break;
			case 8:
				setobj(L, L->top, gt(thvalue(o)));
				break;
			default:
				setnilvalue(L->top);
				break;
			}
			api_incr_top(L);
		}
		static void lua_settable(lua_State * L, int idx) {
			StkId t;
			api_checknelems(L, 2);
			t = index2adr(L, idx);
			api_checkvalidindex(L, t);
			luaV_settable(L, t, L->top - 2, L->top - 1);
			L->top -= 2;
		}
		static void lua_setfield(lua_State * L, int idx, const char *k) {
			StkId t;
			TValue key;
			api_checknelems(L, 1);
			t = index2adr(L, idx);
			api_checkvalidindex(L, t);
			setsvalue(L, &key, luaS_new(L, k));
			luaV_settable(L, t, &key, L->top - 1);
			L->top--;
		}
		static void lua_rawset(lua_State * L, int idx) {
			StkId t;
			api_checknelems(L, 2);
			t = index2adr(L, idx);
			luai_apicheck(L, ttistable(t));
			setobj(L, luaH_set(L, hvalue(t), L->top - 2),
			       L->top - 1);
			luaC_barriert(L, hvalue(t), L->top - 1);
			L->top -= 2;
		}
		static void lua_rawseti(lua_State * L, int idx, int n) {
			StkId o;
			api_checknelems(L, 1);
			o = index2adr(L, idx);
			luai_apicheck(L, ttistable(o));
			setobj(L, luaH_setnum(L, hvalue(o), n), L->top - 1);
			luaC_barriert(L, hvalue(o), L->top - 1);
			L->top--;
		}
		static int lua_setmetatable(lua_State * L, int objindex) {
			TValue *obj;
			Table *mt;
			api_checknelems(L, 1);
			obj = index2adr(L, objindex);
			api_checkvalidindex(L, obj);
			if (ttisnil(L->top - 1))
				mt = NULL;
			else {
				luai_apicheck(L, ttistable(L->top - 1));
				mt = hvalue(L->top - 1);
			}
			switch (ttype(obj)) {
			case 5:{
					hvalue(obj)->metatable = mt;
					if (mt)
						luaC_objbarriert(L, hvalue(obj),
								 mt);
					break;
				}
			case 7:{
					uvalue(obj)->metatable = mt;
					if (mt)
						luaC_objbarrier(L,
								rawuvalue(obj),
								mt);
					break;
				}
			default:{
					G(L)->mt[ttype(obj)] = mt;
					break;
				}
			}
			L->top--;
			return 1;
		}
		static int lua_setfenv(lua_State * L, int idx) {
			StkId o;
			int res = 1;
			api_checknelems(L, 1);
			o = index2adr(L, idx);
			api_checkvalidindex(L, o);
			luai_apicheck(L, ttistable(L->top - 1));
			switch (ttype(o)) {
			case 6:
				clvalue(o)->c.env = hvalue(L->top - 1);
				break;
			case 7:
				uvalue(o)->env = hvalue(L->top - 1);
				break;
			case 8:
				sethvalue(L, gt(thvalue(o)),
					  hvalue(L->top - 1));
				break;
			default:
				res = 0;
				break;
			}
			if (res)
				luaC_objbarrier(L, gcvalue(o),
						hvalue(L->top - 1));
			L->top--;
			return res;
		}
#define adjustresults(L,nres){if(nres==(-1)&&L->top>=L->ci->top)L->ci->top=L->top;}
#define checkresults(L,na,nr)luai_apicheck(L,(nr)==(-1)||(L->ci->top-L->top>=(nr)-(na)))
		static void lua_call(lua_State * L, int nargs, int nresults) {
			StkId func;
			api_checknelems(L, nargs + 1);
			checkresults(L, nargs, nresults);
			func = L->top - (nargs + 1);
			luaD_call(L, func, nresults);
			adjustresults(L, nresults);
		}
		struct CallS {
			StkId func;
			int nresults;
		};
		static void f_call(lua_State * L, void *ud) {
			struct CallS *c = cast(struct CallS *, ud);
			luaD_call(L, c->func, c->nresults);
		}
		static int lua_pcall(lua_State * L, int nargs, int nresults,
				     int errfunc) {
			struct CallS c;
			int status;
			ptrdiff_t func;
			api_checknelems(L, nargs + 1);
			checkresults(L, nargs, nresults);
			if (errfunc == 0)
				func = 0;
			else {
				StkId o = index2adr(L, errfunc);
				api_checkvalidindex(L, o);
				func = savestack(L, o);
			}
			c.func = L->top - (nargs + 1);
			c.nresults = nresults;
			status =
			    luaD_pcall(L, f_call, &c, savestack(L, c.func),
				       func);
			adjustresults(L, nresults);
			return status;
		}
		static int lua_load(lua_State * L, lua_Reader reader,
				    void *data, const char *chunkname) {
			ZIO z;
			int status;
			if (!chunkname)
				chunkname = "?";
			luaZ_init(L, &z, reader, data);
			status = luaD_protectedparser(L, &z, chunkname);
			return status;
		}
		static int lua_error(lua_State * L) {
			api_checknelems(L, 1);
			luaG_errormsg(L);
			return 0;
		}
		static int lua_next(lua_State * L, int idx) {
			StkId t;
			int more;
			t = index2adr(L, idx);
			luai_apicheck(L, ttistable(t));
			more = luaH_next(L, hvalue(t), L->top - 1);
			if (more) {
				api_incr_top(L);
			} else
				L->top -= 1;
			return more;
		}
		static void lua_concat(lua_State * L, int n) {
			api_checknelems(L, n);
			if (n >= 2) {
				luaC_checkGC(L);
				luaV_concat(L, n,
					    cast_int(L->top - L->base) - 1);
				L->top -= (n - 1);
			} else if (n == 0) {
				setsvalue(L, L->top, luaS_newlstr(L, "", 0));
				api_incr_top(L);
			}
		}
		static void *lua_newuserdata(lua_State * L, size_t size) {
			Udata *u;
			luaC_checkGC(L);
			u = luaS_newudata(L, size, getcurrenv(L));
			setuvalue(L, L->top, u);
			api_incr_top(L);
			return u + 1;
		}
#define luaL_getn(L,i)((int)lua_objlen(L,i))
#define luaL_setn(L,i,j)((void)0)
		typedef struct luaL_Reg {
			const char *name;
			lua_CFunction func;
		} luaL_Reg;
		static void luaI_openlib(lua_State * L, const char *libname,
					 const luaL_Reg * l, int nup);
		static int luaL_argerror(lua_State * L, int numarg,
					 const char *extramsg);
		static const char *luaL_checklstring(lua_State * L, int numArg,
						     size_t *l);
		static const char *luaL_optlstring(lua_State * L, int numArg,
						   const char *def, size_t *l);
		static lua_Integer luaL_checkinteger(lua_State * L, int numArg);
		static lua_Integer luaL_optinteger(lua_State * L, int nArg,
						   lua_Integer def);
		static int luaL_error(lua_State * L, const char *fmt, ...);
		static const char *luaL_findtable(lua_State * L, int idx,
						  const char *fname,
						  int szhint);
#define luaL_argcheck(L,cond,numarg,extramsg)((void)((cond)||luaL_argerror(L,(numarg),(extramsg))))
#define luaL_checkstring(L,n)(luaL_checklstring(L,(n),NULL))
#define luaL_optstring(L,n,d)(luaL_optlstring(L,(n),(d),NULL))
#define luaL_checkint(L,n)((int)luaL_checkinteger(L,(n)))
#define luaL_optint(L,n,d)((int)luaL_optinteger(L,(n),(d)))
#define luaL_typename(L,i)lua_typename(L,lua_type(L,(i)))
#define luaL_getmetatable(L,n)(lua_getfield(L,(-10000),(n)))
#define luaL_opt(L,f,n,d)(lua_isnoneornil(L,(n))?(d):f(L,(n)))
		typedef struct luaL_Buffer {
			char *p;
			int lvl;
			lua_State *L;
			char buffer[BUFSIZ];
		} luaL_Buffer;
#define luaL_addchar(B,c)((void)((B)->p<((B)->buffer+BUFSIZ)||luaL_prepbuffer(B)),(*(B)->p++=(char)(c)))
#define luaL_addsize(B,n)((B)->p+=(n))
		static char *luaL_prepbuffer(luaL_Buffer * B);
		static int luaL_argerror(lua_State * L, int narg,
					 const char *extramsg) {
			lua_Debug ar;
			if (!lua_getstack(L, 0, &ar))
				return luaL_error(L, "bad argument #%d (%s)",
						  narg, extramsg);
			lua_getinfo(L, "n", &ar);
			if (strcmp(ar.namewhat, "method") == 0) {
				narg--;
				if (narg == 0)
					return luaL_error(L,
							  "calling "
							  LUA_QL("%s")
							  " on bad self (%s)",
							  ar.name, extramsg);
			}
			if (ar.name == NULL)
				ar.name = "?";
			return luaL_error(L,
					  "bad argument #%d to " LUA_QL("%s")
					  " (%s)", narg, ar.name, extramsg);
		}
		static int luaL_typerror(lua_State * L, int narg,
					 const char *tname) {
			const char *msg =
			    lua_pushfstring(L, "%s expected, got %s",
					    tname, luaL_typename(L, narg));
			return luaL_argerror(L, narg, msg);
		}
		static void tag_error(lua_State * L, int narg, int tag) {
			luaL_typerror(L, narg, lua_typename(L, tag));
		}
		static void luaL_where(lua_State * L, int level) {
			lua_Debug ar;
			if (lua_getstack(L, level, &ar)) {
				lua_getinfo(L, "Sl", &ar);
				if (ar.currentline > 0) {
					lua_pushfstring(L, "%s:%d: ",
							ar.short_src,
							ar.currentline);
					return;
				}
			}
			lua_pushliteral(L, "");
		}
		static int luaL_error(lua_State * L, const char *fmt, ...) {
			va_list argp;
			va_start(argp, fmt);
			luaL_where(L, 1);
			lua_pushvfstring(L, fmt, argp);
			va_end(argp);
			lua_concat(L, 2);
			return lua_error(L);
		}
		static int luaL_newmetatable(lua_State * L, const char *tname) {
			lua_getfield(L, (-10000), tname);
			if (!lua_isnil(L, -1))
				return 0;
			lua_pop(L, 1);
			lua_newtable(L);
			lua_pushvalue(L, -1);
			lua_setfield(L, (-10000), tname);
			return 1;
		}
		static void *luaL_checkudata(lua_State * L, int ud,
					     const char *tname) {
			void *p = lua_touserdata(L, ud);
			if (p != NULL) {
				if (lua_getmetatable(L, ud)) {
					lua_getfield(L, (-10000), tname);
					if (lua_rawequal(L, -1, -2)) {
						lua_pop(L, 2);
						return p;
					}
				}
			}
			luaL_typerror(L, ud, tname);
			return NULL;
		}
		static void luaL_checkstack(lua_State * L, int space,
					    const char *mes) {
			if (!lua_checkstack(L, space))
				luaL_error(L, "stack overflow (%s)", mes);
		}
		static void luaL_checktype(lua_State * L, int narg, int t) {
			if (lua_type(L, narg) != t)
				tag_error(L, narg, t);
		}
		static void luaL_checkany(lua_State * L, int narg) {
			if (lua_type(L, narg) == (-1))
				luaL_argerror(L, narg, "value expected");
		}
		static const char *luaL_checklstring(lua_State * L, int narg,
						     size_t *len) {
			const char *s = lua_tolstring(L, narg, len);
			if (!s)
				tag_error(L, narg, 4);
			return s;
		}
		static const char *luaL_optlstring(lua_State * L, int narg,
						   const char *def,
						   size_t *len) {
			if (lua_isnoneornil(L, narg)) {
				if (len)
					*len = (def ? strlen(def) : 0);
				return def;
			} else
				return luaL_checklstring(L, narg, len);
		}
		static lua_Number luaL_checknumber(lua_State * L, int narg) {
			lua_Number d = lua_tonumber(L, narg);
			if (d == 0 && !lua_isnumber(L, narg))
				tag_error(L, narg, 3);
			return d;
		}
		static lua_Integer luaL_checkinteger(lua_State * L, int narg) {
			lua_Integer d = lua_tointeger(L, narg);
			if (d == 0 && !lua_isnumber(L, narg))
				tag_error(L, narg, 3);
			return d;
		}
		static lua_Integer luaL_optinteger(lua_State * L, int narg,
						   lua_Integer def) {
			return luaL_opt(L, luaL_checkinteger, narg, def);
		}
		static int luaL_getmetafield(lua_State * L, int obj,
					     const char *event) {
			if (!lua_getmetatable(L, obj))
				return 0;
			lua_pushstring(L, event);
			lua_rawget(L, -2);
			if (lua_isnil(L, -1)) {
				lua_pop(L, 2);
				return 0;
			} else {
				lua_remove(L, -2);
				return 1;
			}
		}
		static void luaL_register(lua_State * L, const char *libname,
					  const luaL_Reg * l) {
			luaI_openlib(L, libname, l, 0);
		}
		static int libsize(const luaL_Reg * l) {
			int size = 0;
			for (; l->name; l++)
				size++;
			return size;
		}
		static void luaI_openlib(lua_State * L, const char *libname,
					 const luaL_Reg * l, int nup) {
			if (libname) {
				int size = libsize(l);
				luaL_findtable(L, (-10000), "_LOADED", 1);
				lua_getfield(L, -1, libname);
				if (!lua_istable(L, -1)) {
					lua_pop(L, 1);
					if (luaL_findtable
					    (L, (-10002), libname,
					     size) != NULL)
						luaL_error(L,
							   "name conflict for module "
							   LUA_QL("%s"),
							   libname);
					lua_pushvalue(L, -1);
					lua_setfield(L, -3, libname);
				}
				lua_remove(L, -2);
				lua_insert(L, -(nup + 1));
			}
			for (; l->name; l++) {
				int i;
				for (i = 0; i < nup; i++)
					lua_pushvalue(L, -nup);
				lua_pushcclosure(L, l->func, nup);
				lua_setfield(L, -(nup + 2), l->name);
			}
			lua_pop(L, nup);
		}
		static const char *luaL_findtable(lua_State * L, int idx,
						  const char *fname,
						  int szhint) {
			const char *e;
			lua_pushvalue(L, idx);
			do {
				e = strchr(fname, '.');
				if (e == NULL)
					e = fname + strlen(fname);
				lua_pushlstring(L, fname, e - fname);
				lua_rawget(L, -2);
				if (lua_isnil(L, -1)) {
					lua_pop(L, 1);
					lua_createtable(L, 0,
							(*e ==
							 '.' ? 1 : szhint));
					lua_pushlstring(L, fname, e - fname);
					lua_pushvalue(L, -2);
					lua_settable(L, -4);
				} else if (!lua_istable(L, -1)) {
					lua_pop(L, 2);
					return fname;
				}
				lua_remove(L, -2);
				fname = e + 1;
			} while (*e == '.');
			return NULL;
		}
#define bufflen(B)((B)->p-(B)->buffer)
#define bufffree(B)((size_t)(BUFSIZ-bufflen(B)))
		static int emptybuffer(luaL_Buffer * B) {
			size_t l = bufflen(B);
			if (l == 0)
				return 0;
			else {
				lua_pushlstring(B->L, B->buffer, l);
				B->p = B->buffer;
				B->lvl++;
				return 1;
			}
		}
		static void adjuststack(luaL_Buffer * B) {
			if (B->lvl > 1) {
				lua_State *L = B->L;
				int toget = 1;
				size_t toplen = lua_strlen(L, -1);
				do {
					size_t l = lua_strlen(L, -(toget + 1));
					if (B->lvl - toget + 1 >= (20 / 2)
					    || toplen > l) {
						toplen += l;
						toget++;
					} else
						break;
				} while (toget < B->lvl);
				lua_concat(L, toget);
				B->lvl = B->lvl - toget + 1;
			}
		}
		static char *luaL_prepbuffer(luaL_Buffer * B) {
			if (emptybuffer(B))
				adjuststack(B);
			return B->buffer;
		}
		static void luaL_addlstring(luaL_Buffer * B, const char *s,
					    size_t l) {
			while (l--)
				luaL_addchar(B, *s++);
		}
		static void luaL_pushresult(luaL_Buffer * B) {
			emptybuffer(B);
			lua_concat(B->L, B->lvl);
			B->lvl = 1;
		}
		static void luaL_addvalue(luaL_Buffer * B) {
			lua_State *L = B->L;
			size_t vl;
			const char *s = lua_tolstring(L, -1, &vl);
			if (vl <= bufffree(B)) {
				memcpy(B->p, s, vl);
				B->p += vl;
				lua_pop(L, 1);
			} else {
				if (emptybuffer(B))
					lua_insert(L, -2);
				B->lvl++;
				adjuststack(B);
			}
		}
		static void luaL_buffinit(lua_State * L, luaL_Buffer * B) {
			B->L = L;
			B->p = B->buffer;
			B->lvl = 0;
		}
		typedef struct LoadF {
			int extraline;
			FILE *f;
			char buff[BUFSIZ];
		} LoadF;
		static const char *getF(lua_State * L, void *ud, size_t *size) {
			LoadF *lf = (LoadF *) ud;
			(void)L;
			if (lf->extraline) {
				lf->extraline = 0;
				*size = 1;
				return "\n";
			}
			if (feof(lf->f))
				return NULL;
			*size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);
			return (*size > 0) ? lf->buff : NULL;
		}
		static int errfile(lua_State * L, const char *what,
				   int fnameindex) {
			const char *serr = strerror(errno);
			const char *filename = lua_tostring(L, fnameindex) + 1;
			lua_pushfstring(L, "cannot %s %s: %s", what, filename,
					serr);
			lua_remove(L, fnameindex);
			return (5 + 1);
		}
		static int luaL_loadfile(lua_State * L, const char *filename) {
			LoadF lf;
			int status, readstatus;
			int c;
			int fnameindex = lua_gettop(L) + 1;
			lf.extraline = 0;
			if (filename == NULL) {
				lua_pushliteral(L, "=stdin");
				lf.f = stdin;
			} else {
				lua_pushfstring(L, "@%s", filename);
				lf.f = fopen(filename, "r");
				if (lf.f == NULL)
					return errfile(L, "open", fnameindex);
			}
			c = getc(lf.f);
			if (c == '#') {
				lf.extraline = 1;
				while ((c = getc(lf.f)) != EOF && c != '\n') ;
				if (c == '\n')
					c = getc(lf.f);
			}
			if (c == "\033Lua"[0] && filename) {
				lf.f = freopen(filename, "rb", lf.f);
				if (lf.f == NULL)
					return errfile(L, "reopen", fnameindex);
				while ((c = getc(lf.f)) != EOF
				       && c != "\033Lua"[0]) ;
				lf.extraline = 0;
			}
			ungetc(c, lf.f);
			status = lua_load(L, getF, &lf, lua_tostring(L, -1));
			readstatus = ferror(lf.f);
			if (filename)
				fclose(lf.f);
			if (readstatus) {
				lua_settop(L, fnameindex);
				return errfile(L, "read", fnameindex);
			}
			lua_remove(L, fnameindex);
			return status;
		}
		typedef struct LoadS {
			const char *s;
			size_t size;
		} LoadS;
		static const char *getS(lua_State * L, void *ud, size_t *size) {
			LoadS *ls = (LoadS *) ud;
			(void)L;
			if (ls->size == 0)
				return NULL;
			*size = ls->size;
			ls->size = 0;
			return ls->s;
		}
		static int luaL_loadbuffer(lua_State * L, const char *buff,
					   size_t size, const char *name) {
			LoadS ls;
			ls.s = buff;
			ls.size = size;
			return lua_load(L, getS, &ls, name);
		}
		static void *l_alloc(void *ud, void *ptr, size_t osize,
				     size_t nsize) {
			(void)ud;
			(void)osize;
			if (nsize == 0) {
				free(ptr);
				return NULL;
			} else
				return realloc(ptr, nsize);
		}
		static int panic(lua_State * L) {
			(void)L;
			fprintf(stderr,
				"PANIC: unprotected error in call to Lua API (%s)\n",
				lua_tostring(L, -1));
			return 0;
		}
		static lua_State *luaL_newstate(void) {
			lua_State *L = lua_newstate(l_alloc, NULL);
			if (L)
				lua_atpanic(L, &panic);
			return L;
		}
		static int luaB_tonumber(lua_State * L) {
			int base = luaL_optint(L, 2, 10);
			if (base == 10) {
				luaL_checkany(L, 1);
				if (lua_isnumber(L, 1)) {
					lua_pushnumber(L, lua_tonumber(L, 1));
					return 1;
				}
			} else {
				const char *s1 = luaL_checkstring(L, 1);
				char *s2;
				unsigned long n;
				luaL_argcheck(L, 2 <= base
					      && base <= 36, 2,
					      "base out of range");
				n = strtoul(s1, &s2, base);
				if (s1 != s2) {
					while (isspace((unsigned char)(*s2)))
						s2++;
					if (*s2 == '\0') {
						lua_pushnumber(L,
							       (lua_Number) n);
						return 1;
					}
				}
			}
			lua_pushnil(L);
			return 1;
		}
		static int luaB_error(lua_State * L) {
			int level = luaL_optint(L, 2, 1);
			lua_settop(L, 1);
			if (lua_isstring(L, 1) && level > 0) {
				luaL_where(L, level);
				lua_pushvalue(L, 1);
				lua_concat(L, 2);
			}
			return lua_error(L);
		}
		static int luaB_setmetatable(lua_State * L) {
			int t = lua_type(L, 2);
			luaL_checktype(L, 1, 5);
			luaL_argcheck(L, t == 0 || t == 5, 2,
				      "nil or table expected");
			if (luaL_getmetafield(L, 1, "__metatable"))
				luaL_error(L,
					   "cannot change a protected metatable");
			lua_settop(L, 2);
			lua_setmetatable(L, 1);
			return 1;
		}
		static void getfunc(lua_State * L, int opt) {
			if (lua_isfunction(L, 1))
				lua_pushvalue(L, 1);
			else {
				lua_Debug ar;
				int level =
				    opt ? luaL_optint(L, 1,
						      1) : luaL_checkint(L, 1);
				luaL_argcheck(L, level >= 0, 1,
					      "level must be non-negative");
				if (lua_getstack(L, level, &ar) == 0)
					luaL_argerror(L, 1, "invalid level");
				lua_getinfo(L, "f", &ar);
				if (lua_isnil(L, -1))
					luaL_error(L,
						   "no function environment for tail call at level %d",
						   level);
			}
		}
		static int luaB_setfenv(lua_State * L) {
			luaL_checktype(L, 2, 5);
			getfunc(L, 0);
			lua_pushvalue(L, 2);
			if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
				lua_pushthread(L);
				lua_insert(L, -2);
				lua_setfenv(L, -2);
				return 0;
			} else if (lua_iscfunction(L, -2)
				   || lua_setfenv(L, -2) == 0)
				luaL_error(L,
					   LUA_QL("setfenv")
					   " cannot change environment of given object");
			return 1;
		}
		static int luaB_rawget(lua_State * L) {
			luaL_checktype(L, 1, 5);
			luaL_checkany(L, 2);
			lua_settop(L, 2);
			lua_rawget(L, 1);
			return 1;
		}
		static int luaB_type(lua_State * L) {
			luaL_checkany(L, 1);
			lua_pushstring(L, luaL_typename(L, 1));
			return 1;
		}
		static int luaB_next(lua_State * L) {
			luaL_checktype(L, 1, 5);
			lua_settop(L, 2);
			if (lua_next(L, 1))
				return 2;
			else {
				lua_pushnil(L);
				return 1;
			}
		}
		static int luaB_pairs(lua_State * L) {
			luaL_checktype(L, 1, 5);
			lua_pushvalue(L, lua_upvalueindex(1));
			lua_pushvalue(L, 1);
			lua_pushnil(L);
			return 3;
		}
		static int ipairsaux(lua_State * L) {
			int i = luaL_checkint(L, 2);
			luaL_checktype(L, 1, 5);
			i++;
			lua_pushinteger(L, i);
			lua_rawgeti(L, 1, i);
			return (lua_isnil(L, -1)) ? 0 : 2;
		}
		static int luaB_ipairs(lua_State * L) {
			luaL_checktype(L, 1, 5);
			lua_pushvalue(L, lua_upvalueindex(1));
			lua_pushvalue(L, 1);
			lua_pushinteger(L, 0);
			return 3;
		}
		static int load_aux(lua_State * L, int status) {
			if (status == 0)
				return 1;
			else {
				lua_pushnil(L);
				lua_insert(L, -2);
				return 2;
			}
		}
		static int luaB_loadstring(lua_State * L) {
			size_t l;
			const char *s = luaL_checklstring(L, 1, &l);
			const char *chunkname = luaL_optstring(L, 2, s);
			return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
		}
		static int luaB_loadfile(lua_State * L) {
			const char *fname = luaL_optstring(L, 1, NULL);
			return load_aux(L, luaL_loadfile(L, fname));
		}
		static int luaB_assert(lua_State * L) {
			luaL_checkany(L, 1);
			if (!lua_toboolean(L, 1))
				return luaL_error(L, "%s",
						  luaL_optstring(L, 2,
								 "assertion failed!"));
			return lua_gettop(L);
		}
		static int luaB_unpack(lua_State * L) {
			int i, e, n;
			luaL_checktype(L, 1, 5);
			i = luaL_optint(L, 2, 1);
			e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
			if (i > e)
				return 0;
			n = e - i + 1;
			if (n <= 0 || !lua_checkstack(L, n))
				return luaL_error(L,
						  "too many results to unpack");
			lua_rawgeti(L, 1, i);
			while (i++ < e)
				lua_rawgeti(L, 1, i);
			return n;
		}
		static int luaB_pcall(lua_State * L) {
			int status;
			luaL_checkany(L, 1);
			status = lua_pcall(L, lua_gettop(L) - 1, (-1), 0);
			lua_pushboolean(L, (status == 0));
			lua_insert(L, 1);
			return lua_gettop(L);
		}
		static int luaB_newproxy(lua_State * L) {
			lua_settop(L, 1);
			lua_newuserdata(L, 0);
			if (lua_toboolean(L, 1) == 0)
				return 1;
			else if (lua_isboolean(L, 1)) {
				lua_newtable(L);
				lua_pushvalue(L, -1);
				lua_pushboolean(L, 1);
				lua_rawset(L, lua_upvalueindex(1));
			} else {
				int validproxy = 0;
				if (lua_getmetatable(L, 1)) {
					lua_rawget(L, lua_upvalueindex(1));
					validproxy = lua_toboolean(L, -1);
					lua_pop(L, 1);
				}
				luaL_argcheck(L, validproxy, 1,
					      "boolean or proxy expected");
				lua_getmetatable(L, 1);
			}
			lua_setmetatable(L, 2);
			return 1;
		}
		static const luaL_Reg base_funcs[] = {
			{"assert", luaB_assert},
			{"error", luaB_error},
			{"loadfile", luaB_loadfile},
			{"loadstring", luaB_loadstring},
			{"next", luaB_next},
			{"pcall", luaB_pcall},
			{"rawget", luaB_rawget},
			{"setfenv", luaB_setfenv},
			{"setmetatable", luaB_setmetatable},
			{"tonumber", luaB_tonumber},
			{"type", luaB_type},
			{"unpack", luaB_unpack},
			{NULL, NULL}
		};
		static void auxopen(lua_State * L, const char *name,
				    lua_CFunction f, lua_CFunction u) {
			lua_pushcfunction(L, u);
			lua_pushcclosure(L, f, 1);
			lua_setfield(L, -2, name);
		}
		static void base_open(lua_State * L) {
			lua_pushvalue(L, (-10002));
			lua_setglobal(L, "_G");
			luaL_register(L, "_G", base_funcs);
			lua_pushliteral(L, "Lua 5.1");
			lua_setglobal(L, "_VERSION");
			auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
			auxopen(L, "pairs", luaB_pairs, luaB_next);
			lua_createtable(L, 0, 1);
			lua_pushvalue(L, -1);
			lua_setmetatable(L, -2);
			lua_pushliteral(L, "kv");
			lua_setfield(L, -2, "__mode");
			lua_pushcclosure(L, luaB_newproxy, 1);
			lua_setglobal(L, "newproxy");
		}
		static int luaopen_base(lua_State * L) {
			base_open(L);
			return 1;
		}
#define aux_getn(L,n)(luaL_checktype(L,n,5),luaL_getn(L,n))
		static int tinsert(lua_State * L) {
			int e = aux_getn(L, 1) + 1;
			int pos;
			switch (lua_gettop(L)) {
			case 2:{
					pos = e;
					break;
				}
			case 3:{
					int i;
					pos = luaL_checkint(L, 2);
					if (pos > e)
						e = pos;
					for (i = e; i > pos; i--) {
						lua_rawgeti(L, 1, i - 1);
						lua_rawseti(L, 1, i);
					}
					break;
				}
			default:{
					return luaL_error(L,
							  "wrong number of arguments to "
							  LUA_QL("insert"));
				}
			}
			luaL_setn(L, 1, e);
			lua_rawseti(L, 1, pos);
			return 0;
		}
		static int tremove(lua_State * L) {
			int e = aux_getn(L, 1);
			int pos = luaL_optint(L, 2, e);
			if (!(1 <= pos && pos <= e))
				return 0;
			luaL_setn(L, 1, e - 1);
			lua_rawgeti(L, 1, pos);
			for (; pos < e; pos++) {
				lua_rawgeti(L, 1, pos + 1);
				lua_rawseti(L, 1, pos);
			}
			lua_pushnil(L);
			lua_rawseti(L, 1, e);
			return 1;
		}
		static void addfield(lua_State * L, luaL_Buffer * b, int i) {
			lua_rawgeti(L, 1, i);
			if (!lua_isstring(L, -1))
				luaL_error(L,
					   "invalid value (%s) at index %d in table for "
					   LUA_QL("concat"), luaL_typename(L,
									   -1),
					   i);
			luaL_addvalue(b);
		}
		static int tconcat(lua_State * L) {
			luaL_Buffer b;
			size_t lsep;
			int i, last;
			const char *sep = luaL_optlstring(L, 2, "", &lsep);
			luaL_checktype(L, 1, 5);
			i = luaL_optint(L, 3, 1);
			last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1));
			luaL_buffinit(L, &b);
			for (; i < last; i++) {
				addfield(L, &b, i);
				luaL_addlstring(&b, sep, lsep);
			}
			if (i == last)
				addfield(L, &b, i);
			luaL_pushresult(&b);
			return 1;
		}
		static void set2(lua_State * L, int i, int j) {
			lua_rawseti(L, 1, i);
			lua_rawseti(L, 1, j);
		}
		static int sort_comp(lua_State * L, int a, int b) {
			if (!lua_isnil(L, 2)) {
				int res;
				lua_pushvalue(L, 2);
				lua_pushvalue(L, a - 1);
				lua_pushvalue(L, b - 2);
				lua_call(L, 2, 1);
				res = lua_toboolean(L, -1);
				lua_pop(L, 1);
				return res;
			} else
				return lua_lessthan(L, a, b);
		}
		static void auxsort(lua_State * L, int l, int u) {
			while (l < u) {
				int i, j;
				lua_rawgeti(L, 1, l);
				lua_rawgeti(L, 1, u);
				if (sort_comp(L, -1, -2))
					set2(L, l, u);
				else
					lua_pop(L, 2);
				if (u - l == 1)
					break;
				i = (l + u) / 2;
				lua_rawgeti(L, 1, i);
				lua_rawgeti(L, 1, l);
				if (sort_comp(L, -2, -1))
					set2(L, i, l);
				else {
					lua_pop(L, 1);
					lua_rawgeti(L, 1, u);
					if (sort_comp(L, -1, -2))
						set2(L, i, u);
					else
						lua_pop(L, 2);
				}
				if (u - l == 2)
					break;
				lua_rawgeti(L, 1, i);
				lua_pushvalue(L, -1);
				lua_rawgeti(L, 1, u - 1);
				set2(L, i, u - 1);
				i = l;
				j = u - 1;
				for (;;) {
					while (lua_rawgeti(L, 1, ++i),
					       sort_comp(L, -1, -2)) {
						if (i > u)
							luaL_error(L,
								   "invalid order function for sorting");
						lua_pop(L, 1);
					}
					while (lua_rawgeti(L, 1, --j),
					       sort_comp(L, -3, -1)) {
						if (j < l)
							luaL_error(L,
								   "invalid order function for sorting");
						lua_pop(L, 1);
					}
					if (j < i) {
						lua_pop(L, 3);
						break;
					}
					set2(L, i, j);
				}
				lua_rawgeti(L, 1, u - 1);
				lua_rawgeti(L, 1, i);
				set2(L, u - 1, i);
				if (i - l < u - i) {
					j = l;
					i = i - 1;
					l = i + 2;
				} else {
					j = i + 1;
					i = u;
					u = j - 2;
				}
				auxsort(L, j, i);
			}
		}
		static int sort(lua_State * L) {
			int n = aux_getn(L, 1);
			luaL_checkstack(L, 40, "");
			if (!lua_isnoneornil(L, 2))
				luaL_checktype(L, 2, 6);
			lua_settop(L, 2);
			auxsort(L, 1, n);
			return 0;
		}
		static const luaL_Reg tab_funcs[] = {
			{"concat", tconcat},
			{"insert", tinsert},
			{"remove", tremove},
			{"sort", sort},
			{NULL, NULL}
		};
		static int luaopen_table(lua_State * L) {
			luaL_register(L, "table", tab_funcs);
			return 1;
		}
		static const char *const fnames[] = { "input", "output" };
		static int pushresult(lua_State * L, int i,
				      const char *filename) {
			int en = errno;
			if (i) {
				lua_pushboolean(L, 1);
				return 1;
			} else {
				lua_pushnil(L);
				if (filename)
					lua_pushfstring(L, "%s: %s", filename,
							strerror(en));
				else
					lua_pushfstring(L, "%s", strerror(en));
				lua_pushinteger(L, en);
				return 3;
			}
		}
		static void fileerror(lua_State * L, int arg,
				      const char *filename) {
			lua_pushfstring(L, "%s: %s", filename, strerror(errno));
			luaL_argerror(L, arg, lua_tostring(L, -1));
		}
#define tofilep(L)((FILE**)luaL_checkudata(L,1,"FILE*"))
		static int io_type(lua_State * L) {
			void *ud;
			luaL_checkany(L, 1);
			ud = lua_touserdata(L, 1);
			lua_getfield(L, (-10000), "FILE*");
			if (ud == NULL || !lua_getmetatable(L, 1)
			    || !lua_rawequal(L, -2, -1))
				lua_pushnil(L);
			else if (*((FILE **) ud) == NULL)
				lua_pushliteral(L, "closed file");
			else
				lua_pushliteral(L, "file");
			return 1;
		}
		static FILE *tofile(lua_State * L) {
			FILE **f = tofilep(L);
			if (*f == NULL)
				luaL_error(L, "attempt to use a closed file");
			return *f;
		}
		static FILE **newfile(lua_State * L) {
			FILE **pf =
			    (FILE **) lua_newuserdata(L, sizeof(FILE *));
			*pf = NULL;
			luaL_getmetatable(L, "FILE*");
			lua_setmetatable(L, -2);
			return pf;
		}
		static int io_noclose(lua_State * L) {
			lua_pushnil(L);
			lua_pushliteral(L, "cannot close standard file");
			return 2;
		}
		static int io_pclose(lua_State * L) {
			FILE **p = tofilep(L);
			int ok = lua_pclose(L, *p);
			*p = NULL;
			return pushresult(L, ok, NULL);
		}
		static int io_fclose(lua_State * L) {
			FILE **p = tofilep(L);
			int ok = (fclose(*p) == 0);
			*p = NULL;
			return pushresult(L, ok, NULL);
		}
		static int aux_close(lua_State * L) {
			lua_getfenv(L, 1);
			lua_getfield(L, -1, "__close");
			return (lua_tocfunction(L, -1)) (L);
		}
		static int io_close(lua_State * L) {
			if (lua_isnone(L, 1))
				lua_rawgeti(L, (-10001), 2);
			tofile(L);
			return aux_close(L);
		}
		static int io_gc(lua_State * L) {
			FILE *f = *tofilep(L);
			if (f != NULL)
				aux_close(L);
			return 0;
		}
		static int io_open(lua_State * L) {
			const char *filename = luaL_checkstring(L, 1);
			const char *mode = luaL_optstring(L, 2, "r");
			FILE **pf = newfile(L);
			*pf = fopen(filename, mode);
			return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
		}
		static FILE *getiofile(lua_State * L, int findex) {
			FILE *f;
			lua_rawgeti(L, (-10001), findex);
			f = *(FILE **) lua_touserdata(L, -1);
			if (f == NULL)
				luaL_error(L, "standard %s file is closed",
					   fnames[findex - 1]);
			return f;
		}
		static int g_iofile(lua_State * L, int f, const char *mode) {
			if (!lua_isnoneornil(L, 1)) {
				const char *filename = lua_tostring(L, 1);
				if (filename) {
					FILE **pf = newfile(L);
					*pf = fopen(filename, mode);
					if (*pf == NULL)
						fileerror(L, 1, filename);
				} else {
					tofile(L);
					lua_pushvalue(L, 1);
				}
				lua_rawseti(L, (-10001), f);
			}
			lua_rawgeti(L, (-10001), f);
			return 1;
		}
		static int io_input(lua_State * L) {
			return g_iofile(L, 1, "r");
		}
		static int io_output(lua_State * L) {
			return g_iofile(L, 2, "w");
		}
		static int io_readline(lua_State * L);
		static void aux_lines(lua_State * L, int idx, int toclose) {
			lua_pushvalue(L, idx);
			lua_pushboolean(L, toclose);
			lua_pushcclosure(L, io_readline, 2);
		}
		static int f_lines(lua_State * L) {
			tofile(L);
			aux_lines(L, 1, 0);
			return 1;
		}
		static int io_lines(lua_State * L) {
			if (lua_isnoneornil(L, 1)) {
				lua_rawgeti(L, (-10001), 1);
				return f_lines(L);
			} else {
				const char *filename = luaL_checkstring(L, 1);
				FILE **pf = newfile(L);
				*pf = fopen(filename, "r");
				if (*pf == NULL)
					fileerror(L, 1, filename);
				aux_lines(L, lua_gettop(L), 1);
				return 1;
			}
		}
		static int read_number(lua_State * L, FILE * f) {
			lua_Number d;
			if (fscanf(f, "%lf", &d) == 1) {
				lua_pushnumber(L, d);
				return 1;
			} else {
				lua_pushnil(L);
				return 0;
			}
		}
		static int test_eof(lua_State * L, FILE * f) {
			int c = getc(f);
			ungetc(c, f);
			lua_pushlstring(L, NULL, 0);
			return (c != EOF);
		}
		static int read_line(lua_State * L, FILE * f) {
			luaL_Buffer b;
			luaL_buffinit(L, &b);
			for (;;) {
				size_t l;
				char *p = luaL_prepbuffer(&b);
				if (fgets(p, BUFSIZ, f) == NULL) {
					luaL_pushresult(&b);
					return (lua_objlen(L, -1) > 0);
				}
				l = strlen(p);
				if (l == 0 || p[l - 1] != '\n')
					luaL_addsize(&b, l);
				else {
					luaL_addsize(&b, l - 1);
					luaL_pushresult(&b);
					return 1;
				}
			}
		}
		static int read_chars(lua_State * L, FILE * f, size_t n) {
			size_t rlen;
			size_t nr;
			luaL_Buffer b;
			luaL_buffinit(L, &b);
			rlen = BUFSIZ;
			do {
				char *p = luaL_prepbuffer(&b);
				if (rlen > n)
					rlen = n;
				nr = fread(p, sizeof(char), rlen, f);
				luaL_addsize(&b, nr);
				n -= nr;
			} while (n > 0 && nr == rlen);
			luaL_pushresult(&b);
			return (n == 0 || lua_objlen(L, -1) > 0);
		}
		static int g_read(lua_State * L, FILE * f, int first) {
			int nargs = lua_gettop(L) - 1;
			int success;
			int n;
			clearerr(f);
			if (nargs == 0) {
				success = read_line(L, f);
				n = first + 1;
			} else {
				luaL_checkstack(L, nargs + 20,
						"too many arguments");
				success = 1;
				for (n = first; nargs-- && success; n++) {
					if (lua_type(L, n) == 3) {
						size_t l =
						    (size_t)lua_tointeger(L, n);
						success =
						    (l == 0) ? test_eof(L,
									f) :
						    read_chars(L, f, l);
					} else {
						const char *p =
						    lua_tostring(L, n);
						luaL_argcheck(L, p
							      && p[0] == '*', n,
							      "invalid option");
						switch (p[1]) {
						case 'n':
							success =
							    read_number(L, f);
							break;
						case 'l':
							success =
							    read_line(L, f);
							break;
						case 'a':
							read_chars(L, f,
								   ~((size_t)
								     0));
							success = 1;
							break;
						default:
							return luaL_argerror(L,
									     n,
									     "invalid format");
						}
					}
				}
			}
			if (ferror(f))
				return pushresult(L, 0, NULL);
			if (!success) {
				lua_pop(L, 1);
				lua_pushnil(L);
			}
			return n - first;
		}
		static int io_read(lua_State * L) {
			return g_read(L, getiofile(L, 1), 1);
		}
		static int f_read(lua_State * L) {
			return g_read(L, tofile(L), 2);
		}
		static int io_readline(lua_State * L) {
			FILE *f =
			    *(FILE **) lua_touserdata(L, lua_upvalueindex(1));
			int sucess;
			if (f == NULL)
				luaL_error(L, "file is already closed");
			sucess = read_line(L, f);
			if (ferror(f))
				return luaL_error(L, "%s", strerror(errno));
			if (sucess)
				return 1;
			else {
				if (lua_toboolean(L, lua_upvalueindex(2))) {
					lua_settop(L, 0);
					lua_pushvalue(L, lua_upvalueindex(1));
					aux_close(L);
				}
				return 0;
			}
		}
		static int g_write(lua_State * L, FILE * f, int arg) {
			int nargs = lua_gettop(L) - 1;
			int status = 1;
			for (; nargs--; arg++) {
				if (lua_type(L, arg) == 3) {
					status = status &&
					    fprintf(f, "%.14g",
						    lua_tonumber(L, arg)) > 0;
				} else {
					size_t l;
					const char *s =
					    luaL_checklstring(L, arg, &l);
					status = status
					    && (fwrite(s, sizeof(char), l, f) ==
						l);
				}
			}
			return pushresult(L, status, NULL);
		}
		static int io_write(lua_State * L) {
			return g_write(L, getiofile(L, 2), 1);
		}
		static int f_write(lua_State * L) {
			return g_write(L, tofile(L), 2);
		}
		static int io_flush(lua_State * L) {
			return pushresult(L, fflush(getiofile(L, 2)) == 0,
					  NULL);
		}
		static int f_flush(lua_State * L) {
			return pushresult(L, fflush(tofile(L)) == 0, NULL);
		}
		static const luaL_Reg iolib[] = {
			{"close", io_close},
			{"flush", io_flush},
			{"input", io_input},
			{"lines", io_lines},
			{"open", io_open},
			{"output", io_output},
			{"read", io_read},
			{"type", io_type},
			{"write", io_write},
			{NULL, NULL}
		};
		static const luaL_Reg flib[] = {
			{"close", io_close},
			{"flush", f_flush},
			{"lines", f_lines},
			{"read", f_read},
			{"write", f_write},
			{"__gc", io_gc},
			{NULL, NULL}
		};
		static void createmeta(lua_State * L) {
			luaL_newmetatable(L, "FILE*");
			lua_pushvalue(L, -1);
			lua_setfield(L, -2, "__index");
			luaL_register(L, NULL, flib);
		}
		static void createstdfile(lua_State * L, FILE * f, int k,
					  const char *fname) {
			*newfile(L) = f;
			if (k > 0) {
				lua_pushvalue(L, -1);
				lua_rawseti(L, (-10001), k);
			}
			lua_pushvalue(L, -2);
			lua_setfenv(L, -2);
			lua_setfield(L, -3, fname);
		}
		static void newfenv(lua_State * L, lua_CFunction cls) {
			lua_createtable(L, 0, 1);
			lua_pushcfunction(L, cls);
			lua_setfield(L, -2, "__close");
		}
		static int luaopen_io(lua_State * L) {
			createmeta(L);
			newfenv(L, io_fclose);
			lua_replace(L, (-10001));
			luaL_register(L, "io", iolib);
			newfenv(L, io_noclose);
			createstdfile(L, stdin, 1, "stdin");
			createstdfile(L, stdout, 2, "stdout");
			createstdfile(L, stderr, 0, "stderr");
			lua_pop(L, 1);
			lua_getfield(L, -1, "popen");
			newfenv(L, io_pclose);
			lua_setfenv(L, -2);
			lua_pop(L, 1);
			return 1;
		}
		static int os_pushresult(lua_State * L, int i,
					 const char *filename) {
			int en = errno;
			if (i) {
				lua_pushboolean(L, 1);
				return 1;
			} else {
				lua_pushnil(L);
				lua_pushfstring(L, "%s: %s", filename,
						strerror(en));
				lua_pushinteger(L, en);
				return 3;
			}
		}
		static int os_remove(lua_State * L) {
			const char *filename = luaL_checkstring(L, 1);
			return os_pushresult(L, remove(filename) == 0,
					     filename);
		}
		static int os_exit(lua_State * L) {
			exit(luaL_optint(L, 1, EXIT_SUCCESS));
		}
		static const luaL_Reg syslib[] = {
			{"exit", os_exit},
			{"remove", os_remove},
			{NULL, NULL}
		};
		static int luaopen_os(lua_State * L) {
			luaL_register(L, "os", syslib);
			return 1;
		}
#define uchar(c)((unsigned char)(c))
		static ptrdiff_t posrelat(ptrdiff_t pos, size_t len) {
			if (pos < 0)
				pos += (ptrdiff_t)len + 1;
			return (pos >= 0) ? pos : 0;
		}
		static int str_sub(lua_State * L) {
			size_t l;
			const char *s = luaL_checklstring(L, 1, &l);
			ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
			ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
			if (start < 1)
				start = 1;
			if (end > (ptrdiff_t)l)
				end = (ptrdiff_t)l;
			if (start <= end)
				lua_pushlstring(L, s + start - 1,
						end - start + 1);
			else
				lua_pushliteral(L, "");
			return 1;
		}
		static int str_lower(lua_State * L) {
			size_t l;
			size_t i;
			luaL_Buffer b;
			const char *s = luaL_checklstring(L, 1, &l);
			luaL_buffinit(L, &b);
			for (i = 0; i < l; i++)
				luaL_addchar(&b, tolower(uchar(s[i])));
			luaL_pushresult(&b);
			return 1;
		}
		static int str_upper(lua_State * L) {
			size_t l;
			size_t i;
			luaL_Buffer b;
			const char *s = luaL_checklstring(L, 1, &l);
			luaL_buffinit(L, &b);
			for (i = 0; i < l; i++)
				luaL_addchar(&b, toupper(uchar(s[i])));
			luaL_pushresult(&b);
			return 1;
		}
		static int str_rep(lua_State * L) {
			size_t l;
			luaL_Buffer b;
			const char *s = luaL_checklstring(L, 1, &l);
			int n = luaL_checkint(L, 2);
			luaL_buffinit(L, &b);
			while (n-- > 0)
				luaL_addlstring(&b, s, l);
			luaL_pushresult(&b);
			return 1;
		}
		static int str_byte(lua_State * L) {
			size_t l;
			const char *s = luaL_checklstring(L, 1, &l);
			ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
			ptrdiff_t pose =
			    posrelat(luaL_optinteger(L, 3, posi), l);
			int n, i;
			if (posi <= 0)
				posi = 1;
			if ((size_t)pose > l)
				pose = l;
			if (posi > pose)
				return 0;
			n = (int)(pose - posi + 1);
			if (posi + n <= pose)
				luaL_error(L, "string slice too long");
			luaL_checkstack(L, n, "string slice too long");
			for (i = 0; i < n; i++)
				lua_pushinteger(L, uchar(s[posi + i - 1]));
			return n;
		}
		static int str_char(lua_State * L) {
			int n = lua_gettop(L);
			int i;
			luaL_Buffer b;
			luaL_buffinit(L, &b);
			for (i = 1; i <= n; i++) {
				int c = luaL_checkint(L, i);
				luaL_argcheck(L, uchar(c) == c, i,
					      "invalid value");
				luaL_addchar(&b, uchar(c));
			}
			luaL_pushresult(&b);
			return 1;
		}
		typedef struct MatchState {
			const char *src_init;
			const char *src_end;
			lua_State *L;
			int level;
			struct {
				const char *init;
				ptrdiff_t len;
			} capture[32];
		} MatchState;
		static int check_capture(MatchState * ms, int l) {
			l -= '1';
			if (l < 0 || l >= ms->level
			    || ms->capture[l].len == (-1))
				return luaL_error(ms->L,
						  "invalid capture index");
			return l;
		}
		static int capture_to_close(MatchState * ms) {
			int level = ms->level;
			for (level--; level >= 0; level--)
				if (ms->capture[level].len == (-1))
					return level;
			return luaL_error(ms->L, "invalid pattern capture");
		}
		static const char *classend(MatchState * ms, const char *p) {
			switch (*p++) {
			case '%':{
					if (*p == '\0')
						luaL_error(ms->L,
							   "malformed pattern (ends with "
							   LUA_QL("%%") ")");
					return p + 1;
				}
			case '[':{
					if (*p == '^')
						p++;
					do {
						if (*p == '\0')
							luaL_error(ms->L,
								   "malformed pattern (missing "
								   LUA_QL("]")
								   ")");
						if (*(p++) == '%' && *p != '\0')
							p++;
					} while (*p != ']');
					return p + 1;
				}
			default:{
					return p;
				}
			}
		}
		static int match_class(int c, int cl) {
			int res;
			switch (tolower(cl)) {
			case 'a':
				res = isalpha(c);
				break;
			case 'c':
				res = iscntrl(c);
				break;
			case 'd':
				res = isdigit(c);
				break;
			case 'l':
				res = islower(c);
				break;
			case 'p':
				res = ispunct(c);
				break;
			case 's':
				res = isspace(c);
				break;
			case 'u':
				res = isupper(c);
				break;
			case 'w':
				res = isalnum(c);
				break;
			case 'x':
				res = isxdigit(c);
				break;
			case 'z':
				res = (c == 0);
				break;
			default:
				return (cl == c);
			}
			return (islower(cl) ? res : !res);
		}
		static int matchbracketclass(int c, const char *p,
					     const char *ec) {
			int sig = 1;
			if (*(p + 1) == '^') {
				sig = 0;
				p++;
			}
			while (++p < ec) {
				if (*p == '%') {
					p++;
					if (match_class(c, uchar(*p)))
						return sig;
				} else if ((*(p + 1) == '-') && (p + 2 < ec)) {
					p += 2;
					if (uchar(*(p - 2)) <= c
					    && c <= uchar(*p))
						return sig;
				} else if (uchar(*p) == c)
					return sig;
			}
			return !sig;
		}
		static int singlematch(int c, const char *p, const char *ep) {
			switch (*p) {
			case '.':
				return 1;
			case '%':
				return match_class(c, uchar(*(p + 1)));
			case '[':
				return matchbracketclass(c, p, ep - 1);
			default:
				return (uchar(*p) == c);
			}
		}
		static const char *match(MatchState * ms, const char *s,
					 const char *p);
		static const char *matchbalance(MatchState * ms, const char *s,
						const char *p) {
			if (*p == 0 || *(p + 1) == 0)
				luaL_error(ms->L, "unbalanced pattern");
			if (*s != *p)
				return NULL;
			else {
				int b = *p;
				int e = *(p + 1);
				int cont = 1;
				while (++s < ms->src_end) {
					if (*s == e) {
						if (--cont == 0)
							return s + 1;
					} else if (*s == b)
						cont++;
				}
			}
			return NULL;
		}
		static const char *max_expand(MatchState * ms, const char *s,
					      const char *p, const char *ep) {
			ptrdiff_t i = 0;
			while ((s + i) < ms->src_end
			       && singlematch(uchar(*(s + i)), p, ep))
				i++;
			while (i >= 0) {
				const char *res = match(ms, (s + i), ep + 1);
				if (res)
					return res;
				i--;
			}
			return NULL;
		}
		static const char *min_expand(MatchState * ms, const char *s,
					      const char *p, const char *ep) {
			for (;;) {
				const char *res = match(ms, s, ep + 1);
				if (res != NULL)
					return res;
				else if (s < ms->src_end
					 && singlematch(uchar(*s), p, ep))
					s++;
				else
					return NULL;
			}
		}
		static const char *start_capture(MatchState * ms, const char *s,
						 const char *p, int what) {
			const char *res;
			int level = ms->level;
			if (level >= 32)
				luaL_error(ms->L, "too many captures");
			ms->capture[level].init = s;
			ms->capture[level].len = what;
			ms->level = level + 1;
			if ((res = match(ms, s, p)) == NULL)
				ms->level--;
			return res;
		}
		static const char *end_capture(MatchState * ms, const char *s,
					       const char *p) {
			int l = capture_to_close(ms);
			const char *res;
			ms->capture[l].len = s - ms->capture[l].init;
			if ((res = match(ms, s, p)) == NULL)
				ms->capture[l].len = (-1);
			return res;
		}
		static const char *match_capture(MatchState * ms, const char *s,
						 int l) {
			size_t len;
			l = check_capture(ms, l);
			len = ms->capture[l].len;
			if ((size_t)(ms->src_end - s) >= len &&
			    memcmp(ms->capture[l].init, s, len) == 0)
				return s + len;
			else
				return NULL;
		}
		static const char *match(MatchState * ms, const char *s,
					 const char *p) {
 init:
			switch (*p) {
			case '(':{
					if (*(p + 1) == ')')
						return start_capture(ms, s,
								     p + 2,
								     (-2));
					else
						return start_capture(ms, s,
								     p + 1,
								     (-1));
				}
			case ')':{
					return end_capture(ms, s, p + 1);
				}
			case '%':{
					switch (*(p + 1)) {
					case 'b':{
							s = matchbalance(ms, s,
									 p + 2);
							if (s == NULL)
								return NULL;
							p += 4;
							goto init;
						}
					case 'f':{
							const char *ep;
							char previous;
							p += 2;
							if (*p != '[')
								luaL_error(ms->
									   L,
									   "missing "
									   LUA_QL
									   ("[")
									   " after "
									   LUA_QL
									   ("%%f")
									   " in pattern");
							ep = classend(ms, p);
							previous =
							    (s ==
							     ms->
							     src_init) ? '\0' :
							    *(s - 1);
							if (matchbracketclass
							    (uchar(previous), p,
							     ep - 1)
							    ||
							    !matchbracketclass
							    (uchar(*s), p,
							     ep - 1))
								return NULL;
							p = ep;
							goto init;
						}
					default:{
							if (isdigit
							    (uchar(*(p + 1)))) {
								s = match_capture(ms, s, uchar(*(p + 1)));
								if (s == NULL)
									return
									    NULL;
								p += 2;
								goto init;
							}
							goto dflt;
						}
					}
				}
			case '\0':{
					return s;
				}
			case '$':{
					if (*(p + 1) == '\0')
						return (s ==
							ms->src_end) ? s : NULL;
					else
						goto dflt;
				}
			default:
 dflt:				{
					const char *ep = classend(ms, p);
					int m = s < ms->src_end
					    && singlematch(uchar(*s), p, ep);
					switch (*ep) {
					case '?':{
							const char *res;
							if (m
							    &&
							    ((res =
							      match(ms, s + 1,
								    ep + 1)) !=
							     NULL))
								return res;
							p = ep + 1;
							goto init;
						}
					case '*':{
							return max_expand(ms, s,
									  p,
									  ep);
						}
					case '+':{
							return (m ?
								max_expand(ms,
									   s +
									   1, p,
									   ep) :
								NULL);
						}
					case '-':{
							return min_expand(ms, s,
									  p,
									  ep);
						}
					default:{
							if (!m)
								return NULL;
							s++;
							p = ep;
							goto init;
						}
					}
				}
			}
		}
		static const char *lmemfind(const char *s1, size_t l1,
					    const char *s2, size_t l2) {
			if (l2 == 0)
				return s1;
			else if (l2 > l1)
				return NULL;
			else {
				const char *init;
				l2--;
				l1 = l1 - l2;
				while (l1 > 0
				       && (init =
					   (const char *)memchr(s1, *s2,
								l1)) != NULL) {
					init++;
					if (memcmp(init, s2 + 1, l2) == 0)
						return init - 1;
					else {
						l1 -= init - s1;
						s1 = init;
					}
				}
				return NULL;
			}
		}
		static void push_onecapture(MatchState * ms, int i,
					    const char *s, const char *e) {
			if (i >= ms->level) {
				if (i == 0)
					lua_pushlstring(ms->L, s, e - s);
				else
					luaL_error(ms->L,
						   "invalid capture index");
			} else {
				ptrdiff_t l = ms->capture[i].len;
				if (l == (-1))
					luaL_error(ms->L, "unfinished capture");
				if (l == (-2))
					lua_pushinteger(ms->L,
							ms->capture[i].init -
							ms->src_init + 1);
				else
					lua_pushlstring(ms->L,
							ms->capture[i].init, l);
			}
		}
		static int push_captures(MatchState * ms, const char *s,
					 const char *e) {
			int i;
			int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
			luaL_checkstack(ms->L, nlevels, "too many captures");
			for (i = 0; i < nlevels; i++)
				push_onecapture(ms, i, s, e);
			return nlevels;
		}
		static int str_find_aux(lua_State * L, int find) {
			size_t l1, l2;
			const char *s = luaL_checklstring(L, 1, &l1);
			const char *p = luaL_checklstring(L, 2, &l2);
			ptrdiff_t init =
			    posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
			if (init < 0)
				init = 0;
			else if ((size_t)(init) > l1)
				init = (ptrdiff_t)l1;
			if (find && (lua_toboolean(L, 4) ||
				     strpbrk(p, "^$*+?.([%-") == NULL)) {
				const char *s2 =
				    lmemfind(s + init, l1 - init, p, l2);
				if (s2) {
					lua_pushinteger(L, s2 - s + 1);
					lua_pushinteger(L, s2 - s + l2);
					return 2;
				}
			} else {
				MatchState ms;
				int anchor = (*p == '^') ? (p++, 1) : 0;
				const char *s1 = s + init;
				ms.L = L;
				ms.src_init = s;
				ms.src_end = s + l1;
				do {
					const char *res;
					ms.level = 0;
					if ((res = match(&ms, s1, p)) != NULL) {
						if (find) {
							lua_pushinteger(L,
									s1 - s +
									1);
							lua_pushinteger(L,
									res -
									s);
							return
							    push_captures(&ms,
									  NULL,
									  0) +
							    2;
						} else
							return
							    push_captures(&ms,
									  s1,
									  res);
					}
				} while (s1++ < ms.src_end && !anchor);
			}
			lua_pushnil(L);
			return 1;
		}
		static int str_find(lua_State * L) {
			return str_find_aux(L, 1);
		}
		static int str_match(lua_State * L) {
			return str_find_aux(L, 0);
		}
		static int gmatch_aux(lua_State * L) {
			MatchState ms;
			size_t ls;
			const char *s =
			    lua_tolstring(L, lua_upvalueindex(1), &ls);
			const char *p = lua_tostring(L, lua_upvalueindex(2));
			const char *src;
			ms.L = L;
			ms.src_init = s;
			ms.src_end = s + ls;
			for (src =
			     s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
			     src <= ms.src_end; src++) {
				const char *e;
				ms.level = 0;
				if ((e = match(&ms, src, p)) != NULL) {
					lua_Integer newstart = e - s;
					if (e == src)
						newstart++;
					lua_pushinteger(L, newstart);
					lua_replace(L, lua_upvalueindex(3));
					return push_captures(&ms, src, e);
				}
			}
			return 0;
		}
		static int gmatch(lua_State * L) {
			luaL_checkstring(L, 1);
			luaL_checkstring(L, 2);
			lua_settop(L, 2);
			lua_pushinteger(L, 0);
			lua_pushcclosure(L, gmatch_aux, 3);
			return 1;
		}
		static void add_s(MatchState * ms, luaL_Buffer * b,
				  const char *s, const char *e) {
			size_t l, i;
			const char *news = lua_tolstring(ms->L, 3, &l);
			for (i = 0; i < l; i++) {
				if (news[i] != '%')
					luaL_addchar(b, news[i]);
				else {
					i++;
					if (!isdigit(uchar(news[i])))
						luaL_addchar(b, news[i]);
					else if (news[i] == '0')
						luaL_addlstring(b, s, e - s);
					else {
						push_onecapture(ms,
								news[i] - '1',
								s, e);
						luaL_addvalue(b);
					}
				}
			}
		}
		static void add_value(MatchState * ms, luaL_Buffer * b,
				      const char *s, const char *e) {
			lua_State *L = ms->L;
			switch (lua_type(L, 3)) {
			case 3:
			case 4:{
					add_s(ms, b, s, e);
					return;
				}
			case 6:{
					int n;
					lua_pushvalue(L, 3);
					n = push_captures(ms, s, e);
					lua_call(L, n, 1);
					break;
				}
			case 5:{
					push_onecapture(ms, 0, s, e);
					lua_gettable(L, 3);
					break;
				}
			}
			if (!lua_toboolean(L, -1)) {
				lua_pop(L, 1);
				lua_pushlstring(L, s, e - s);
			} else if (!lua_isstring(L, -1))
				luaL_error(L,
					   "invalid replacement value (a %s)",
					   luaL_typename(L, -1));
			luaL_addvalue(b);
		}
		static int str_gsub(lua_State * L) {
			size_t srcl;
			const char *src = luaL_checklstring(L, 1, &srcl);
			const char *p = luaL_checkstring(L, 2);
			int tr = lua_type(L, 3);
			int max_s = luaL_optint(L, 4, srcl + 1);
			int anchor = (*p == '^') ? (p++, 1) : 0;
			int n = 0;
			MatchState ms;
			luaL_Buffer b;
			luaL_argcheck(L, tr == 3 || tr == 4 ||
				      tr == 6 || tr == 5, 3,
				      "string/function/table expected");
			luaL_buffinit(L, &b);
			ms.L = L;
			ms.src_init = src;
			ms.src_end = src + srcl;
			while (n < max_s) {
				const char *e;
				ms.level = 0;
				e = match(&ms, src, p);
				if (e) {
					n++;
					add_value(&ms, &b, src, e);
				}
				if (e && e > src)
					src = e;
				else if (src < ms.src_end)
					luaL_addchar(&b, *src++);
				else
					break;
				if (anchor)
					break;
			}
			luaL_addlstring(&b, src, ms.src_end - src);
			luaL_pushresult(&b);
			lua_pushinteger(L, n);
			return 2;
		}
		static void addquoted(lua_State * L, luaL_Buffer * b, int arg) {
			size_t l;
			const char *s = luaL_checklstring(L, arg, &l);
			luaL_addchar(b, '"');
			while (l--) {
				switch (*s) {
				case '"':
				case '\\':
				case '\n':{
						luaL_addchar(b, '\\');
						luaL_addchar(b, *s);
						break;
					}
				case '\r':{
						luaL_addlstring(b, "\\r", 2);
						break;
					}
				case '\0':{
						luaL_addlstring(b, "\\000", 4);
						break;
					}
				default:{
						luaL_addchar(b, *s);
						break;
					}
				}
				s++;
			}
			luaL_addchar(b, '"');
		}
		static const char *scanformat(lua_State * L,
					      const char *strfrmt, char *form) {
			const char *p = strfrmt;
			while (*p != '\0' && strchr("-+ #0", *p) != NULL)
				p++;
			if ((size_t)(p - strfrmt) >= sizeof("-+ #0"))
				luaL_error(L,
					   "invalid format (repeated flags)");
			if (isdigit(uchar(*p)))
				p++;
			if (isdigit(uchar(*p)))
				p++;
			if (*p == '.') {
				p++;
				if (isdigit(uchar(*p)))
					p++;
				if (isdigit(uchar(*p)))
					p++;
			}
			if (isdigit(uchar(*p)))
				luaL_error(L,
					   "invalid format (width or precision too long)");
			*(form++) = '%';
			strncpy(form, strfrmt, p - strfrmt + 1);
			form += p - strfrmt + 1;
			*form = '\0';
			return p;
		}
		static void addintlen(char *form) {
			size_t l = strlen(form);
			char spec = form[l - 1];
			strcpy(form + l - 1, "l");
			form[l + sizeof("l") - 2] = spec;
			form[l + sizeof("l") - 1] = '\0';
		}
		static int str_format(lua_State * L) {
			int top = lua_gettop(L);
			int arg = 1;
			size_t sfl;
			const char *strfrmt = luaL_checklstring(L, arg, &sfl);
			const char *strfrmt_end = strfrmt + sfl;
			luaL_Buffer b;
			luaL_buffinit(L, &b);
			while (strfrmt < strfrmt_end) {
				if (*strfrmt != '%')
					luaL_addchar(&b, *strfrmt++);
				else if (*++strfrmt == '%')
					luaL_addchar(&b, *strfrmt++);
				else {
					char form[(sizeof("-+ #0") +
						   sizeof("l") + 10)];
					char buff[512];
					if (++arg > top)
						luaL_argerror(L, arg,
							      "no value");
					strfrmt = scanformat(L, strfrmt, form);
					switch (*strfrmt++) {
					case 'c':{
							sprintf(buff, form,
								(int)
								luaL_checknumber
								(L, arg));
							break;
						}
					case 'd':
					case 'i':{
							addintlen(form);
							sprintf(buff, form,
								(long)
								luaL_checknumber
								(L, arg));
							break;
						}
					case 'o':
					case 'u':
					case 'x':
					case 'X':{
							addintlen(form);
							sprintf(buff, form,
								(unsigned long)
								luaL_checknumber
								(L, arg));
							break;
						}
					case 'e':
					case 'E':
					case 'f':
					case 'g':
					case 'G':{
							sprintf(buff, form,
								(double)
								luaL_checknumber
								(L, arg));
							break;
						}
					case 'q':{
							addquoted(L, &b, arg);
							continue;
						}
					case 's':{
							size_t l;
							const char *s =
							    luaL_checklstring(L,
									      arg,
									      &l);
							if (!strchr(form, '.')
							    && l >= 100) {
								lua_pushvalue(L,
									      arg);
								luaL_addvalue
								    (&b);
								continue;
							} else {
								sprintf(buff,
									form,
									s);
								break;
							}
						}
					default:{
							return luaL_error(L,
									  "invalid option "
									  LUA_QL
									  ("%%%c")
									  " to "
									  LUA_QL
									  ("format"),
									  *
									  (strfrmt
									   -
									   1));
						}
					}
					luaL_addlstring(&b, buff, strlen(buff));
				}
			}
			luaL_pushresult(&b);
			return 1;
		}
		static const luaL_Reg strlib[] = {
			{"byte", str_byte},
			{"char", str_char},
			{"find", str_find},
			{"format", str_format},
			{"gmatch", gmatch},
			{"gsub", str_gsub},
			{"lower", str_lower},
			{"match", str_match},
			{"rep", str_rep},
			{"sub", str_sub},
			{"upper", str_upper},
			{NULL, NULL}
		};
		static void createmetatable(lua_State * L) {
			lua_createtable(L, 0, 1);
			lua_pushliteral(L, "");
			lua_pushvalue(L, -2);
			lua_setmetatable(L, -2);
			lua_pop(L, 1);
			lua_pushvalue(L, -2);
			lua_setfield(L, -2, "__index");
			lua_pop(L, 1);
		}
		static int luaopen_string(lua_State * L) {
			luaL_register(L, "string", strlib);
			createmetatable(L);
			return 1;
		}
		static const luaL_Reg lualibs[] = {
			{"", luaopen_base},
			{"table", luaopen_table},
			{"io", luaopen_io},
			{"os", luaopen_os},
			{"string", luaopen_string},
			{NULL, NULL}
		};
		static void luaL_openlibs(lua_State * L) {
			const luaL_Reg *lib = lualibs;
			for (; lib->func; lib++) {
				lua_pushcfunction(L, lib->func);
				lua_pushstring(L, lib->name);
				lua_call(L, 1, 0);
			}
		}
		typedef unsigned int UB;
		static UB barg(lua_State * L, int idx) {
			union {
				lua_Number n;
				U64 b;
			} bn;
			bn.n = lua_tonumber(L, idx) + 6755399441055744.0;
			if (bn.n == 0.0 && !lua_isnumber(L, idx))
				luaL_typerror(L, idx, "number");
			return (UB) bn.b;
		}
#define BRET(b)lua_pushnumber(L,(lua_Number)(int)(b));return 1;
		static int tobit(lua_State * L) {
		BRET(barg(L, 1))}
		static int bnot(lua_State * L) {
		BRET(~barg(L, 1))}
		static int band(lua_State * L) {
			int i;
			UB b = barg(L, 1);
			for (i = lua_gettop(L); i > 1; i--)
				b &= barg(L, i);
		BRET(b)}
		static int bor(lua_State * L) {
			int i;
			UB b = barg(L, 1);
			for (i = lua_gettop(L); i > 1; i--)
				b |= barg(L, i);
		BRET(b)}
		static int bxor(lua_State * L) {
			int i;
			UB b = barg(L, 1);
			for (i = lua_gettop(L); i > 1; i--)
				b ^= barg(L, i);
		BRET(b)}
		static int lshift(lua_State * L) {
			UB b = barg(L, 1), n = barg(L, 2) & 31;
		BRET(b << n)}
		static int rshift(lua_State * L) {
			UB b = barg(L, 1), n = barg(L, 2) & 31;
		BRET(b >> n)}
		static int arshift(lua_State * L) {
			UB b = barg(L, 1), n = barg(L, 2) & 31;
		BRET((int)b >> n)}
		static int rol(lua_State * L) {
			UB b = barg(L, 1), n = barg(L, 2) & 31;
		BRET((b << n) | (b >> (32 - n)))}
		static int ror(lua_State * L) {
			UB b = barg(L, 1), n = barg(L, 2) & 31;
		BRET((b >> n) | (b << (32 - n)))}
		static int bswap(lua_State * L) {
			UB b = barg(L, 1);
			b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) <<
							       8) | (b << 24);
		BRET(b)}
		static int tohex(lua_State * L) {
			UB b = barg(L, 1);
			int n = lua_isnone(L, 2) ? 8 : (int)barg(L, 2);
			const char *hexdigits = "0123456789abcdef";
			char buf[8];
			int i;
			if (n < 0) {
				n = -n;
				hexdigits = "0123456789ABCDEF";
			}
			if (n > 8)
				n = 8;
			for (i = (int)n; --i >= 0;) {
				buf[i] = hexdigits[b & 15];
				b >>= 4;
			}
			lua_pushlstring(L, buf, (size_t)n);
			return 1;
		}
		static const struct luaL_Reg bitlib[] = {
			{"tobit", tobit},
			{"bnot", bnot},
			{"band", band},
			{"bor", bor},
			{"bxor", bxor},
			{"lshift", lshift},
			{"rshift", rshift},
			{"arshift", arshift},
			{"rol", rol},
			{"ror", ror},
			{"bswap", bswap},
			{"tohex", tohex},
			{NULL, NULL}
		};
		int main(int argc, char **argv) {
			lua_State *L = luaL_newstate();
			int i;
			luaL_openlibs(L);
			luaL_register(L, "bit", bitlib);
			if (argc < 2)
				return sizeof(void *);
			lua_createtable(L, 0, 1);
			lua_pushstring(L, argv[1]);
			lua_rawseti(L, -2, 0);
			lua_setglobal(L, "arg");
			if (luaL_loadfile(L, argv[1]))
				goto err;
			for (i = 2; i < argc; i++)
				lua_pushstring(L, argv[i]);
			if (lua_pcall(L, argc - 2, 0, 0)) {
 err:
				fprintf(stderr, "Error: %s\n",
					lua_tostring(L, -1));
				return 1;
			}
			lua_close(L);
			return 0;
		}
